Close all open transactions, sessions and connections with clients - this is invoked by JVM shutdown hook
170870
public void shutdown(){
        transactionListenerSet.forEach(transactionListener -> transactionListener.close(null));
        transactionListenerSet.clear();
        openSessions.values().forEach(SessionImpl::close);
    }
1324985
public void closeSession() throws HibernateException
    {
        Session s = threadSession.get();
        threadSession.set(null);
        if (s != null)
        {
            s.close();
        }
        
        Transaction tx = threadTransaction.get();
        if (tx != null)
        {
            threadTransaction.set(null);
            //log warning todo
        }
    }
194544
public void dispose() {
        try {
            connection.close();
        } catch (final Exception e) {
            LOGGER.log(Level.ERROR, "Disposes transaction [" + getId() + "] failed", e);
        } finally {
            isActive = false;
            connection = null;
            JdbcRepository.TX.set(null);
        }
    }
205894
function () {
        // just to be sure! clear all items in the connections object. they should be cleared by now
        util.each(this.connections, function (value, prop, conns) {
            try {
                value.release();
            }
            catch (e) { } // nothing to do with error
            delete conns[prop];
        });

        // now execute end on the databases. will end pool if pool, or otherwise will execute whatever
        // `end` that has been exposed by db.js
        util.each(Transaction.databases, function (value, prop, databases) {
            value.end();
            databases[prop] = null;
        });
    }
738374
@Override
	public void close() {
		transactionManager.close();
		if (coverageHandlerRef.get() != null) {
			coverageHandlerRef.get().onSqlAgentClose();
		}
	}
508080
@Override
    public void destroy() // PK20881
    {
        if (tc.isEntryEnabled())
            Tr.entry(tc, "destroy");

        // Dummy transactionWrappers may not be in any table and so
        // will not have a resourceCallback registered to remove them.
        if (_resourceCallback != null)
            _resourceCallback.destroy();

        _wrappers.remove(_transaction.getGlobalId());

        //      Do not remove connection with the TransactionImpl.  This will delay garbage
//      collection until the TransactionWrapper is garbage collected.
//      There is a window when an incoming request can access the remoteable object
//      (ie WSCoordinator or CoordinatorResource) and get access to the TransactionWrapper
//      while destroy() is called by another thread as the synchronization is on the
//      TransactionWrapper.  When the incoming request gets control, it will find that
//      _transaction is null.  Rather than check for this case, we leave the connection
//      to the TransactionImpl and its associated TransactionState.  The code above will
//      then check the transaction state and respond appropriately.  These checks are
//      already required as the superior may retry requests, etc.
//        _transaction = null;

        if (tc.isEntryEnabled())
            Tr.exit(tc, "destroy");
    }
344764
public void close() {
        if (connected.compareAndSet(true, false)) {
            // remove handshake flag
            session.removeAttribute(Constants.HANDSHAKE_COMPLETE);
            // clear the delay queue
            queue.clear();
            // whether to attempt a nice close or a forceful one
            if (WebSocketTransport.isNiceClose()) {
                // send a proper ws close
                Packet packet = Packet.build(Constants.CLOSE_MESSAGE_BYTES, MessageType.CLOSE);
                WriteFuture writeFuture = session.write(packet);
                writeFuture.addListener(new IoFutureListener<WriteFuture>() {

                    @Override
                    public void operationComplete(WriteFuture future) {
                        if (future.isWritten()) {
                            log.debug("Close message written");
                            // only set on success for now to skip boolean check later
                            session.setAttribute(Constants.STATUS_CLOSE_WRITTEN, Boolean.TRUE);
                        }
                        future.removeListener(this);
                    }

                });
                // adjust close routine to allow for flushing
                CloseFuture closeFuture = session.closeOnFlush();
                closeFuture.addListener(new IoFutureListener<CloseFuture>() {

                    public void operationComplete(CloseFuture future) {
                        if (future.isClosed()) {
                            log.debug("Connection is closed");
                        } else {
                            log.debug("Connection is not yet closed");
                        }
                        future.removeListener(this);
                    }

                });
            } else {
                // force close
                CloseFuture closeFuture = session.closeNow();
                closeFuture.addListener(new IoFutureListener<CloseFuture>() {

                    public void operationComplete(CloseFuture future) {
                        if (future.isClosed()) {
                            log.debug("Connection is closed");
                        } else {
                            log.debug("Connection is not yet closed");
                        }
                        future.removeListener(this);
                    }

                });
            }
        }
    }
502129
public synchronized void shutdownDbmsPools() {
        //force shutdown
        //runnable
        datasourceCleaner.shutdown();
        datasourceCleaner = null;
        //shell for the runnable
        cleanerThread.interrupt();//stop the thread
        cleanerThread = null;

        if (dbmsPoolTable == null) {
            return;
        }
        Enumeration<String> allDbmsKeys = dbmsPoolTable.keys();
        while (allDbmsKeys.hasMoreElements()) {
            String dbmsKey = allDbmsKeys.nextElement();
            PooledDataSourceProvider provider = this.getProvider(dbmsKey);
            Hashtable<String, DataSource> dsTable = dbmsPoolTable.get(dbmsKey);
            for (DataSource ds : dsTable.values()) {
                try {
                    provider.closePooledDataSource(ds);
                } catch (SQLException e) {
//          todo          logger.error("Failed to close datasource in dbms poolKey = "
//                            + dbmsKey);
                }
            }
            dsTable.clear();
        }
        dbmsPoolTable.clear();
        dbmsPoolTable = null;
    }
52241
@Override
    public synchronized void close() {

        if (isClosed) {
            return;
        }

        rollback(false);

        try {
            database.logger.writeToLog(this, Tokens.T_DISCONNECT);
        } catch (HsqlException e) {}

        sessionData.closeAllNavigators();
        sessionData.persistentStoreCollection.clearAllTables();
        sessionData.closeResultCache();
        database.compiledStatementManager.removeSession(sessionId);
        database.sessionManager.removeSession(this);
        database.closeIfLast();

        database                  = null;
        user                      = null;
        rowActionList             = null;
        sessionContext.savepoints = null;
        intConnection             = null;
        sessionContext            = null;
        lastIdentity              = null;
        isClosed                  = true;
    }
836914
@Override
	protected void onSessionClose()
	{
    	// Rollback updates
	    try
	    {
        	if (hasPendingUpdates())
                rollbackUpdates(true,true, null);
	    }
        catch (JMSException e)
        {
            ErrorTools.log(e, log);
        }
    	
    	super.onSessionClose();
    }
903881
public void terminateAllConnections(){
		this.terminationLock.lock();
		try{
			// close off all connections.
			for (int i=0; i < this.pool.partitionCount; i++) {
				this.pool.partitions[i].setUnableToCreateMoreTransactions(false); // we can create new ones now, this is an optimization
				List<ConnectionHandle> clist = new LinkedList<ConnectionHandle>(); 
				this.pool.partitions[i].getFreeConnections().drainTo(clist);
				for (ConnectionHandle c: clist){
					this.pool.destroyConnection(c);
				}

			}
		} finally {
			this.terminationLock.unlock();
		}
	}
154430
private function closeConnections()
    {
        if (!$this->container->hasParameter('doctrine_phpcr.sessions')) {
            return;
        }

        foreach ($this->container->getParameter('doctrine_phpcr.sessions') as $id) {
            if ($this->container instanceof IntrospectableContainerInterface && !$this->container->initialized($id)) {
                continue;
            }

            $session = $this->container->get($id);
            if (!$session instanceof Session) {
                return;
            }

            $session->getTransport()->logout();
        }
    }
1311723
@Override
    public void close()
    {
        if ( treeState.compareAndSet(TreeState.STARTED, TreeState.CLOSED) )
        {
            client.getConnectionStateListenable().removeListener(connectionStateListener);
            listeners.clear();
            executorService.shutdown();
            try
            {
                root.wasDeleted();
            }
            catch ( Exception e )
            {
                ThreadUtils.checkInterrupted(e);
                handleException(e);
            }
        }
    }
862724
public void shutdown ()
    {
        // close all of the connections
        for (Map.Entry<String, Mapping> entry : _keys.entrySet()) {
            entry.getValue().closeConnection(entry.getKey());
        }

        // clear out our mapping tables
        _keys.clear();
        _idents.clear();
    }
17569
protected final void shutdown()
                    throws ObjectManagerException
    {
        final String methodName = "shutdown";
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this, cclass, methodName);

        Exception exceptionCaughtDuringShutdown = null;

        synchronized (this) {
            // Make the state change.
            setState(ObjectManagerState.nextStateForStartShutdown);
        } // synchronized (this).

        // Block the creation of new transactions.
        currentMaximumActiveTransactions = 0; // Don't start any new transactions.

        // Defect 496893
        // Call our event callbacks at this point as we are no 
        // longer open for business.
        synchronized (this)
        {
            if (callbacks != null)
            {
                java.util.Iterator it = callbacks.iterator();
                while (it.hasNext())
                {
                    ObjectManagerEventCallback callback = (ObjectManagerEventCallback) it.next();

                    callback.notification(ObjectManagerEventCallback.objectManagerStopped, null);
                }
            }
        }

        // Back out all transactions that are not in prepared state.
        if (Tracing.isAnyTracingEnabled() && trace.isDebugEnabled())
            trace.debug(this,
                        cclass,
                        methodName,
                        "Backout remaining unprepared transactions:1231");

        // Count the number of transactions in each state.
        int[] transactionsPerState = new int[InternalTransaction.stateNames.length];
        try {
            for (java.util.Iterator registeredTransactionIterator = registeredInternalTransactions.values().iterator(); registeredTransactionIterator.hasNext();) {
                InternalTransaction registeredTransaction = (InternalTransaction) registeredTransactionIterator.next();
                synchronized (registeredTransaction) {
                    if (registeredTransaction.state == Transaction.stateInactive
                        || registeredTransaction.state == Transaction.stateActiveNonPersistent
                        || registeredTransaction.state == Transaction.stateActivePersistent) {

                        // Check that the transaction did not commit or backout before we synchronized on it.
                        if (registeredInternalTransactions.get(new Long(registeredTransaction.getLogicalUnitOfWork().identifier)) == registeredTransaction) {
                            // Use getExternalTransaction because we need to ensure that any application will have its external
                            // Transaction terminated.
                            Transaction transaction = registeredTransaction.getExternalTransaction();
                            transaction.setTerminationReason(Transaction.terminatedShutdown);
                            transaction.backout(false); // Do not reuse this transaction.
                        } //  if ( registeredInternalTransactions...
                    } // if (   registeredTransaction.state...

                    transactionsPerState[registeredTransaction.state]++;
                } // synchronized (registeredTransaction).
            } // for registeredInternalTransactions.
        } catch (Exception exception) {
            // No FFDC Code Needed.
            ObjectManager.ffdc.processException(this,
                                                cclass,
                                                methodName,
                                                exception,
                                                "1:1263:1.62");
            exceptionCaughtDuringShutdown = exception;
        } // try.

        if (Tracing.isAnyTracingEnabled() && trace.isDebugEnabled()) {
            Object[] objects = new Object[transactionsPerState.length];
            for (int i = 0; i < transactionsPerState.length; i++)
                objects[i] = InternalTransaction.stateNames[i] + "=" + Integer.toString(transactionsPerState[i]);
            trace.debug(this, cclass, methodName, "Transactions in each state:1271");
            trace.debug(this, cclass, methodName, objects);
        } // if (Tracing.isAnyTracingEnabled() && trace.isDebugEnabled()).

        synchronized (this) {
            // Make the state change.
            setState(ObjectManagerState.nextStateForShutdown);
        } // synchronized (this).

        try {
            // Take a checkpoint. ObjectStores with STRATEGY_SAVE_ONLY_ON_SHUTDOWN can now safely
            // update their data.
            if (checkpointHelper != null) {
                checkpointHelper.waitForCheckpoint(true);
                checkpointHelper.shutdown(); // Terminate the checkpoint thread.
                checkpointHelper = null;
            } // if (checkpointHelper != null).
        } catch (Exception exception) {
            // No FFDC Code Needed.
            ObjectManager.ffdc.processException(this,
                                                cclass,
                                                methodName,
                                                exception,
                                                "1:1294:1.62");
            exceptionCaughtDuringShutdown = exception;
        } // try.

        // Set all active transactions to a state that wont allow any more actions.
        // We cannot do this before the checkpoint as this sets the InternalTransactions
        // into stateTerminated and excludes them from the checkpoint. As a consequence
        // applications might get data into the log after the last checkpoint has started.
        try {
            for (java.util.Iterator transactionIterator = registeredInternalTransactions.values().iterator(); transactionIterator.hasNext();) {
                InternalTransaction internalTransaction = (InternalTransaction) transactionIterator.next();
                internalTransaction.shutdown();
            } // for... registeredInternalTransactions.
        } catch (Exception exception) {
            // No FFDC Code Needed.
            ObjectManager.ffdc.processException(this,
                                                cclass,
                                                methodName,
                                                exception,
                                                "1:1315:1.62");
            exceptionCaughtDuringShutdown = exception;
        } // try.

        //    if (reportStatistics) { // Stop monitoring statistics.
        //      if (statisticsHelper != null)
        //        statisticsHelper.shutdown();
        //      statisticsHelper = null;
        //    } // if (reportStatistics)

        // Close all of the ObjecStores.
        synchronized (objectStores) {
            java.util.Iterator objectStoreIterator = objectStores.values().iterator();
            while (objectStoreIterator.hasNext()) {
                try {
                    ObjectStore objectStore = (ObjectStore) objectStoreIterator.next();
                    objectStore.close();
                } catch (Exception exception) {
                    // No FFDC Code Needed.
                    ObjectManager.ffdc.processException(this, cclass, methodName, exception, "1:1334:1.62");
                    exceptionCaughtDuringShutdown = exception;
                } // try.
            } // While objectStoreIterator.hasNext().
        } // synchronized (objectStores).

        // Close the logger.
        try {
            if (logOutput != null) {
                logOutput.close();
                logOutput = null;
            } // if (logOutput != null).
        } catch (Exception exception) {
            // No FFDC Code Needed.
            ObjectManager.ffdc.processException(this,
                                                cclass,
                                                methodName,
                                                exception,
                                                "1:1352:1.62");
            exceptionCaughtDuringShutdown = exception;
        } // try.

        // Close the log file and realease the lock on it.
        try {
            if (logLock != null)
                logLock.release();
            if (logFile != null)
                logFile.close();
        } catch (java.io.IOException exception) {
            // No FFDC Code Needed.
            ObjectManager.ffdc.processException(this,
                                                cclass,
                                                methodName,
                                                exception,
                                                "1:1368:1.62");

            if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                trace.exit(this,
                           cclass,
                           methodName,
                           "via PermanentIOException");
            throw new PermanentIOException(this,
                                           exception);
        } // catch (java.io.IOException exception).

        synchronized (ObjectManager.objectManagerStates) {
            ObjectManager.objectManagerStates.remove(logFileName);
        } // synchronized (ObjectManager.objectManagerStates).

        // Help garbage collection.
        registeredInternalTransactions.clear();
        registeredInternalTransactions = null;

        // Let any waiters know we are closed for business.
        synchronized (this) {
            notifyAll();
        }

        trace.debug(cclass, methodName, "ObjectManager using logFile " + logFileName + " has shut down.");

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this,
                       cclass,
                       methodName
                       , new Object[] { exceptionCaughtDuringShutdown });
        if (exceptionCaughtDuringShutdown != null)
            throw new UnexpectedExceptionException(this,
                                                   exceptionCaughtDuringShutdown);
    } // shutdown().

    /**
     * A non blocking request to shutdown the ObjectManager.
     * Used by helper threads when they encounter a fatal error.
     */
    protected void requestShutdown()
    {
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this,
                        cclass,
                        "shutdown");

        new ShutdownHelper();

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this,
                       cclass,
                       "requestShutdown");
    } // requestShutdown().

    /**
     * Terminates the ObjectManagerState, without taking a checkpoint.
     * The allows the ObjectManager to be restarted as if it had crashed.
     * Used for testing emergency restart and also for performing an emergency shutdown
     * if a fatal error has been detected.
     * This form of shutdown continues even if it encounters errors.
     * 
     * @throws ObjectManagerException
     */
    protected final void shutdownFast()
                    throws ObjectManagerException
    {
        final String methodName = "shutdownFast";
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this,
                        cclass,
                        methodName);

        Exception exceptionCaughtDuringShutdown = null;

        if (!inShutdown())
        {
            synchronized (this) {
                // Make the state change.
                setState(ObjectManagerState.nextStateForStartShutdown);
            } // synchronized (this).

            // Defect 496893
            // Call our event callbacks at this point as we are no 
            // longer open for business.
            notifyCallbacks(ObjectManagerEventCallback.objectManagerStopped, null);

            // Terminate the checkpoint thread.
            try {
                if (checkpointHelper != null) {
                    checkpointHelper.shutdown();
                    checkpointHelper = null;
                } // if (checkpointHelper != null).
            } catch (Exception exception) {
                // No FFDC Code Needed.
                ObjectManager.ffdc.processException(this,
                                                    cclass,
                                                    methodName,
                                                    exception,
                                                    "1:1470:1.62");
                exceptionCaughtDuringShutdown = exception;
            } // try.

            // Now that the CheckpointHelper has stopped we can move to stopped state
            // knowing that the ObjectStores will not be flushed while we are in stopped state. 

            synchronized (this) {
                // Make the state change.
                setState(ObjectManagerState.nextStateForShutdown);
            } // synchronized (this).

            // Close all of the ObjecStores.
            synchronized (objectStores) {
                java.util.Iterator objectStoreIterator = objectStores.values().iterator();
                while (objectStoreIterator.hasNext()) {
                    try {
                        ObjectStore objectStore = (ObjectStore) objectStoreIterator.next();
                        objectStore.close();
                    } catch (Exception exception) {
                        // No FFDC Code Needed.
                        ObjectManager.ffdc.processException(this, cclass, methodName, exception, "1:1491:1.62");
                        exceptionCaughtDuringShutdown = exception;
                    } // try.
                } // while objectStoreIterator.hasNext().
            } // synchronized (objectStores).

            // Close the logger.
            try {
                if (logOutput != null) {
                    logOutput.close();
                    logOutput = null;
                } // if (logOutput != null).
            } catch (Exception exception) {
                // No FFDC Code Needed.
                ObjectManager.ffdc.processException(this,
                                                    cclass,
                                                    methodName,
                                                    exception,
                                                    "1:1509:1.62");
                exceptionCaughtDuringShutdown = exception;
            } // try.

            try {
                if (logLock != null)
                    logLock.release();
                if (logFile != null)
                    logFile.close();
            } catch (java.io.IOException exception) {
                // No FFDC Code Needed.
                ObjectManager.ffdc.processException(this,
                                                    cclass,
                                                    methodName,
                                                    exception,
                                                    "1:1524:1.62");

                if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                    trace.exit(this,
                               cclass,
                               methodName,
                               "PermanentIOException:1530");
                throw new PermanentIOException(this,
                                               exception);
            } // catch (java.io.IOException exception).

            synchronized (ObjectManager.objectManagerStates) {
                ObjectManager.objectManagerStates.remove(logFileName);
            } // synchronized (ObjectManager.objectManagerStates).

            // Let any waiters know we are ready for business.
            synchronized (this) {
                notifyAll();
            }
        }// end of if(!inshutdown)

        trace.debug(cclass, methodName, "ObjectManager using logFile " + logFileName + " has shut down without performing a final checkpoint");

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this,
                       cclass,
                       methodName,
                       new Object[] { exceptionCaughtDuringShutdown });
        if (exceptionCaughtDuringShutdown != null)
            throw new UnexpectedExceptionException(this,
                                                   exceptionCaughtDuringShutdown);
    } // shutdownFast().

    /**
     * Recognise the existence of an ObjectStore used by this ObjectManager.
     * It is possible to move an objectStore to another ObjectManager and to change its
     * name. To move or rename an ObjectStore deRegister it then Create a new ObjectStore
     * with the same file moved to its new location, or with a different ObjectManager.
     * This will work so long as the ObjectStore identifier is not in use in the
     * new ObjectManager. Be aware that if the store is added to another ObjectManager
     * which had previously used the ObjectStore identifier there may be phantom
     * references to the Objects in the moved store. Also there may be objects in
     * the moved store which are unreachable because they are referenced by objects
     * in the old ObjectManager.
     * 
     * @param objectStore to be registered with this ObjectManager. The name must be currently unknown in the
     *            ObjectManager.
     * @throws ObjectManagerException, with no change made.
     */
    protected void registerObjectStore(ObjectStore objectStore)
                    throws ObjectManagerException {
        final String methodName = "registerObjectStore";
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this,
                        cclass,
                        methodName,
                        new Object[] { objectStore });

        synchronized (objectStores) {

            ObjectStore existingObjectStore = getObjectStoreByName(objectStore.getName());
            if (existingObjectStore != null) {
                if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                    trace.exit(this,
                               cclass,
                               methodName,
                               new Object[] { "DuplicateObjectStoreNameException:1594",
                                             objectStore.getName() });
                throw new DuplicateObjectStoreNameException(this,
                                                            objectStore.getName(),
                                                            existingObjectStore);
            } // if (existingObjectStore != null).

            objectStore.open(this); // Now ready for use.

            // If this a new ObjectStore, as opposed to one that has been recovered from a serialized version
            // in a checkpoint or from a file, then set its identifier.
            if (objectStore.getIdentifier() == ObjectStore.IDENTIFIER_NOT_SET) {
                // Allocate a new Identifier for the Object Store, which we know is unique.
                maximumObjectStoreIdentifier++;
                objectStore.setIdentifier((int) maximumObjectStoreIdentifier);
            } else {

                // The identifier is already set. Presumably because this is an old store being added to the
                // ObjectManager again. Check that its identifier is not already in use and move the
                // maximumObjectStoreIdentifier past this one.
                existingObjectStore = (ObjectStore) objectStores.get(new Integer(objectStore.getIdentifier()));
                if (existingObjectStore != null) {
                    objectStore.close();
                    if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                        trace.exit(this,
                                   cclass,
                                   methodName,
                                   new Object[] { "DuplicateObjectStoreNameException:1621",
                                                 objectStore.getName() });
                    throw new DuplicateObjectStoreIdentifierException(this,
                                                                      objectStore.getName(),
                                                                      objectStore.getIdentifier(),
                                                                      existingObjectStore);

                } // if duplicate identifier.
                maximumObjectStoreIdentifier = Math.max(maximumObjectStoreIdentifier, objectStore.getIdentifier());
            } // if (objectStore.getIdentifier() == ObjectStore.IDENTIFIER_NOT_SET).

            Transaction transaction = getTransaction();
            transaction.lock(this);

            // We are about to change the ObjectManagerState so we will need to compensate for any failure
            // if we fail before we commit the transaction. We don't worry abut the mamximumObjectStoreIdentfier
            // because it has been allocated to the store and could legitimately be used by it if the registration
            // is retried later but before the ObjectManager shuts down.
            try {
                objectStores.put(new Integer(objectStore.getIdentifier()),
                                 objectStore);
                // We may have previously added ObjectManagerState and we set ourselves to state ready at construction time
                // so we replace, rather than add.
                transaction.replace(this);

                // We can now use the ObjectStore, we can also use it during recovery because the replace operation
                // will have made it available again.

                // It the ObjectStore holds restart data,
                // create or reset the namedObjects map.
                Token namedObjectsToken = null;
                if (objectStore.getContainsRestartData()) {
                    TreeMap namedObjectsTree = getNamedObjects(objectStore, transaction);
                    namedObjectsToken = namedObjectsTree.getToken();
                    if (namedObjects != null) {
                        // Sync up what we found with what we have.
                        namedObjectsTree.clear(transaction);
                        namedObjectsTree.putAll((TreeMap) namedObjects.getManagedObject(), transaction);
                    } // if (namedObjects != null).

                } // if (objectStore.getContainsRestartData()).

                // Also save backup copies of ObjectManagerstate.
                saveClonedState(transaction);
                // Adjust the size of the space reserved for a CheckpointStartLogRecord. If this fails
                // the reference to the transaction will be found by the garbage collector and backed out.
                long newCheckpointStartLogRecordSize = ((new CheckpointStartLogRecord(this)).getBytesLeft() / FileLogOutput.pageSize + 1) * FileLogOutput.pageSize;
                logOutput.reserve(newCheckpointStartLogRecordSize - checkpointStartLogRecordSize);
                checkpointStartLogRecordSize = newCheckpointStartLogRecordSize;

                transaction.commit(false);

                // Now all the updates have been done make any new namedObjects visible.
                if (namedObjects == null)
                    namedObjects = namedObjectsToken;

            } catch (ObjectManagerException exception) {
                // No FFDC Code Needed.
                ObjectManager.ffdc.processException(this,
                                                    cclass,
                                                    methodName,
                                                    exception,
                                                    "1:1683:1.62");
                objectStores.remove(new Integer(objectStore.getIdentifier()));
                transaction.backout(false);

                if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                    trace.exit(this, cclass, methodName, new Object[] { exception });
                throw exception;
            } // try...

        } // synchronized (objectStores).

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this,
                       cclass,
                       methodName);
    } // registerObjectStore().

    /**
     * Recognise an ObjectStore by a new logical name at the next start of the ObjectManager.
     * 
     * @param objectStore to be renamed.
     * @param newName of the store.
     * @throws ObjectManagerException
     */
    protected void renameObjectStore(ObjectStore objectStore, String newName)
                    throws ObjectManagerException {
        final String methodName = "renameObjectStore";
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this,
                        cclass,
                        methodName,
                        new Object[] { objectStore, newName });

        synchronized (objectStores) {
            // Is this store registered, if not there is nothing to do?
            ObjectStore existingObjectStore = getObjectStoreByName(objectStore.getName());
            if (existingObjectStore == null) {
                if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                    trace.exit(this,
                               cclass,
                               methodName,
                               new Object[] { "Store not registered:1724" });
                return;
            }

            // Is the newName currently in use?
            existingObjectStore = getObjectStoreByName(newName);
            if (existingObjectStore != null) {
                if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                    trace.exit(this,
                               cclass,
                               methodName,
                               new Object[] { "DuplicateObjectStoreNameException:1735",
                                             newName,
                                             objectStore.getName() });
                throw new DuplicateObjectStoreNameException(this,
                                                            newName,
                                                            existingObjectStore);
            } // if (existingObjectStore != null).

            Transaction transaction = getTransaction();
            transaction.lock(this);

            String oldName = objectStore.getName();
            // We are about to change the ObjectManagerState so we will need to compensate for any failure
            // if we fail before we commit the transaction. We don't worry abut the mamximumObjectStoreIdentfier
            // because it has been allocated to the store and could legitimately be used by it if the registration
            // is retried later but before the ObjectManager shuts down.
            try {
                objectStore.setLogicalName(newName);
                // We may have previously added ObjectManagerState and we set ourselves to state ready at construction time
                // so we replace, rather than add.
                transaction.replace(this);

                // Also save backup copies of ObjectManagerstate.
                saveClonedState(transaction);
                // Adjust the size of the space reserved for a CheckpointStartLogRecord. If this fails
                // the reference to the transaction will be found by the garbage collector and backed out.
                long newCheckpointStartLogRecordSize = ((new CheckpointStartLogRecord(this)).getBytesLeft() / FileLogOutput.pageSize + 1) * FileLogOutput.pageSize;
                logOutput.reserve(newCheckpointStartLogRecordSize - checkpointStartLogRecordSize);
                checkpointStartLogRecordSize = newCheckpointStartLogRecordSize;

                transaction.commit(false);

            } catch (ObjectManagerException exception) {
                // No FFDC Code Needed.
                ObjectManager.ffdc.processException(this,
                                                    cclass,
                                                    methodName,
                                                    exception,
                                                    "1:1773:1.62");
                if (objectStore instanceof AbstractObjectStore)
                    ((AbstractObjectStore) objectStore).storeName = oldName;
                transaction.backout(false);

                if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                    trace.exit(this, cclass, methodName, new Object[] { exception });
                throw exception;
            } // try...
        } // synchronized (objectStores).

        // Force a full checkpoint so that the caller can be sure that the log will start from
        // a checkpoint containing the new name.
        waitForCheckpoint(true);

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this,
                       cclass,
                       methodName);
    } // renameObjectStore().

    /**
     * Locate the namedObjects tree in an Object Store and create it if necessary.
     * 
     * @param objectStore which should contain the namedObjects tree.
     * @param transaction controlling any creation.
     * @return TreeMap the NamedObjects.
     * @throws ObjectManagerException
     */
    private final TreeMap getNamedObjects(ObjectStore objectStore,
                                          Transaction transaction)
                    throws ObjectManagerException
    {
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this,
                        cclass,
                        "getNamedObjects",
                        new Object[] { objectStore, transaction });

        //  Locate any existing copy.
        Token namedObjectsToken = new Token(objectStore,
                                            ObjectStore.namedObjectTreeIdentifier.longValue());
        // Swap for the definitive Token, if there is one.
        namedObjectsToken = objectStore.like(namedObjectsToken);
        TreeMap namedObjectsTree = (TreeMap) namedObjectsToken.getManagedObject();

        // First time through make a TreeMap.
        if (namedObjectsTree == null) {
            namedObjectsTree = new TreeMap();
            namedObjectsToken.setManagedObject(namedObjectsTree);
            namedObjectsTree.reserveAndAdd(transaction, objectStore);
        } // if (namedObjectsTree == null).

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this,
                       cclass,
                       "getNamedObjects",
                       new Object[] { namedObjectsTree });
        return namedObjectsTree;
    } // getNamedObjects().

    /**
     * Cease to recognise the existence of an ObjectStore used by this ObjectManager.
     * 
     * @param objectStore to be deRegistered from this ObjectManager.
     *            The name must be currently known in the ObjectManager.
     * @throws ObjectManagerException
     */
    protected final void deRegisterObjectStore(ObjectStore objectStore)
                    throws ObjectManagerException {
        final String methodName = "deRegisterObjectStore";
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this, cclass, methodName, new Object[] { objectStore });

        // Flush out as much data from the store as we can. If there are any in flight
        // transactions their updates will not get applied to the store after now.
        waitForCheckpoint(objectStore.getPersistence());

        synchronized (objectStores) {
            Transaction transaction = getTransaction();
            transaction.lock(this);

            // See if the ObjectStore contains the nameObjects Tree before we close it
            // and destroy the namedObjects ManagedObject.
            if (namedObjects != null) {
                if (namedObjects.getObjectStore() == objectStore) {
                    namedObjects = null;
                } // if (namedObjects.getObjectStore()...
            } // if (namedObjects != null).

            objectStore.close();
            objectStores.remove(new Integer(objectStore.getIdentifier()));

            transaction.replace(this);

            saveClonedState(transaction);

            // Adjust the size of the space reserved for a CheckpointStartLogRecord. If this fails
            // the reference to the transaction will be found by the garbage collector and backed out.
            long newCheckpointStartLogRecordSize = ((new CheckpointStartLogRecord(this)).getBytesLeft() / FileLogOutput.pageSize + 1) * FileLogOutput.pageSize;
            logOutput.reserve(newCheckpointStartLogRecordSize - checkpointStartLogRecordSize);
            checkpointStartLogRecordSize = newCheckpointStartLogRecordSize;
            transaction.commit(false);

            // Look for a new definitive copy of the namedObjects Tree, if necessary.
            setDefinitiveNamedObjects();
        } // synchronized (objectStores).

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this, cclass, methodName);
    } // deRegisterObjectStore().

    /**
     * Establish the definitive namedObjects tree in namedObjects, if not already set.
     * Caller must be synchronised on objectStores.
     */
    private void setDefinitiveNamedObjects()
    {
        for (java.util.Iterator objectStoreIterator = objectStores.values().iterator(); objectStoreIterator.hasNext() && namedObjects == null;) {
            ObjectStore objectStore = (ObjectStore) objectStoreIterator.next();

            if (objectStore.getContainsRestartData()) {
                // Locate any existing copy.
                Token namedObjectsToken = new Token(objectStore,
                                                    ObjectStore.namedObjectTreeIdentifier.longValue());
                // Swap for the definitive Token, if there is one.
                namedObjects = objectStore.like(namedObjectsToken);
            } // if (objectStore.getContainsRestartData()).
        } // for ( ObjectStores...
    } // setDefinitiveNamedObjects().

    /**
     * Locate an ObjectStore used by this objectManager.
     * 
     * @param objectStoreIdentifier The unique identifier for the ObjectStore.
     * @return ObjectStore found matching the identifier.
     * @throws ObjectManagerException
     */
    protected ObjectStore getObjectStore(int objectStoreIdentifier)
                    throws ObjectManagerException
    {
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this,
                        cclass,
                        "getObjectStore",
                        new Integer(objectStoreIdentifier));

        ObjectStore objectStore = null; // ObjectStore to return.
        if (objectStoreIdentifier == defaultObjectStoreIdentifier)
            objectStore = defaultObjectStore;
        else {
            synchronized (objectStores) {
                objectStore = (ObjectStore) objectStores.get(new Integer(objectStoreIdentifier));
                if (objectStore == null) {
                    if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                        trace.exit(this,
                                   cclass,
                                   "getOjectStore",
                                   "via NonEexistantObjectStoreException"
                                                   + " objectStoreIdentifier="
                                                   + objectStoreIdentifier
                                                   + "(int)");
                    throw new NonExistentObjectStoreException(this,
                                                              objectStoreIdentifier);
                } // if(objectStore == null).
            } // synchronized (objectStores).
        } // if (objectStoreIdentifier == defaultObjectStoreIdentifier).

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this,
                       cclass,
                       "getObjectStore",
                       objectStore);
        return objectStore;
    } // getObjectStore().

    /**
     * Locate an ObjectStore used by this objectManager.
     * 
     * @param objectStoreName which is the name of the ObjectStore.
     * @return ObjectStore found matching the identifier.
     * @throws ObjectManagerException
     */
    protected final ObjectStore getObjectStore(String objectStoreName)
                    throws ObjectManagerException
    {
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this,
                        cclass,
                        "getObjectStore",
                        "objectStoreName=" + objectStoreName + "(String)");

        ObjectStore objectStore = null; // ObjectStore to return.
        synchronized (objectStores) {
            objectStore = getObjectStoreByName(objectStoreName);
        } // synchronized (objectStores).

        if (objectStore == null) {
            if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                trace.exit(this,
                           cclass,
                           "getObjectStore",
                           "via UnknownObjectStoreException" + " objectStoreName=" + objectStoreName + "(String)");
            throw new UnknownObjectStoreException(this,
                                                  objectStoreName);
        } // if(objectStore == null).

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this,
                       cclass,
                       "getObjectStore",
                       "returns objectStore=" + objectStore + "(ObjectStore)");
        return objectStore;
    } // End of method getObjectStore.

    /**
     * Locate an ObjectStore used by this objectManager by comparing its name.
     * The caller must already be synchronized on objectManagerstate.objectStores.
     * 
     * @param objectStoreName which is the name of the ObjectStore.
     * @return ObjectStore found matching the identifier or null if there is none.
     * @throws ObjectManagerException
     */
    private final ObjectStore getObjectStoreByName(String objectStoreName)
                    throws ObjectManagerException
    {
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this,
                        cclass,
                        "getObjectStoreByName",
                        new String(objectStoreName));

        ObjectStore objectStore = null; // ObjectStore to return.
        // Look for an existing ObjectStore of the same name.
        // We dont keep an index by name as this is only used infrequently and there
        // usually are only a few ObjectStores.
        java.util.Iterator objectStoreIterator = objectStores.values()
                        .iterator();
        while (objectStoreIterator.hasNext() && objectStore == null) {
            ObjectStore existingObjectStore = (ObjectStore) objectStoreIterator.next();
            if (existingObjectStore.getName()
                            .equals(objectStoreName)) {
                objectStore = existingObjectStore;
            } // if (existingObjectStore.getName...
        } // While objectStoreIterator.hasNext().

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this,
                       cclass,
                       "getObjectStoreByName",
                       "returns objectStore=" + objectStore + "(ObjectStore)");
        return objectStore;
    } // End of method getObjectStoreByName.

    /**
     * Create an iterator over all ObjectStores known to this ObjectManager.
     * 
     * @return java.util.Iterator over ObjectStores.
     * @throws ObjectManagerException
     */
    final java.util.Iterator getObjectStoreIterator()
                    throws ObjectManagerException {
        final String methodName = "getObjectStoreIterator";
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this, cclass, methodName);

        // make a copy of the objecStores map because the caller cannot synchronise on it.
        java.util.ArrayList storesList = new java.util.ArrayList(objectStores.values());
        java.util.Iterator objectStoreIterator = storesList.iterator();

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this, cclass, methodName, objectStoreIterator);
        return objectStoreIterator;
    } // getObjectStoreIterator().

    /**
     * Factory method to create or reuse a transaction for use with the ObjectManager.
     * 
     * To detect orphaned transactions, ie. transactions not referenced elsewhere in the JVM. we will keep a reference to
     * the internalTransaction and make a weak reference to the container we pass to the application. When the container
     * Transaction appears on the orphanTransactionsQueue we know the calling application has lost all references to it.
     * At this point we can attempt to reuse it.
     * 
     * @return Transaction the new transaction.
     * @throws ObjectManagerException
     */
    protected final Transaction getTransaction()
                    throws ObjectManagerException
    {
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this,
                        cclass,
                        "getTransaction");

        InternalTransaction internalTransaction = (InternalTransaction) freeTransactions.removeOne();

        if (internalTransaction != null) {
            registerTransaction(internalTransaction);
            if (gatherStatistics)
                reusedTransactions++;

        } else {
            // We need to make a new InternalTransaction.
            synchronized (registeredInternalTransactions) {
                if (totalTransactions >= maximumActiveTransactions) {
                    if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                        trace.exit(this,
                                   cclass,
                                   "getTransaction",
                                   new Object[] { new Long(totalTransactions),
                                                 new Long(maximumActiveTransactions) });
                    throw new TooManyTransactionsException(this,
                                                           maximumActiveTransactions);
                } // if (totalTransactions >= maximumActiveTransactions)

                if (totalTransactions >= currentMaximumActiveTransactions) {
                    if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                        trace.exit(this,
                                   cclass,
                                   "getTransaction",
                                   new Object[] { new Long(totalTransactions),
                                                 new Long(currentMaximumActiveTransactions) });
                    throw new TransactionCapacityExceededException(this,
                                                                   totalTransactions,
                                                                   currentMaximumActiveTransactions);
                } // if (totalTransactions >= currentMaximumActiveTransactions)

                // Make a new transaction.
                internalTransaction = new InternalTransaction(this,
                                                              new LogicalUnitOfWork(++maximumLogicalUnitOfWorkIdentifier));
                totalTransactions++;
            } // synchronized (registeredInternalTransactions).
        } // if (internalTransaction != null).

        Transaction transaction = internalTransaction.getExternalTransaction();

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this,
                       cclass,
                       "getTransaction",
                       transaction);
        return transaction;
    } // getTransaction().

    /**
     * Recognise the existance of a transaction involving this objectManager.
     * 
     * @param internalTransaction to be registered.
     * @throws ObjectManagerException
     */
    protected final void registerTransaction(InternalTransaction internalTransaction)
                    throws ObjectManagerException {
        final String methodName = "registerTransaction";
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this, cclass, methodName, internalTransaction);

        LogicalUnitOfWork logicalUnitOfWork = internalTransaction.getLogicalUnitOfWork();
        InternalTransaction registeredTransaction = (InternalTransaction) registeredInternalTransactions.put(new Long(logicalUnitOfWork.identifier),
                                                                                                             internalTransaction);
        if (registeredTransaction != null) {
            // Make the duplicate transaction useless.
            registeredTransaction.terminate(Transaction.terminatedDuplicate);
            if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                trace.exit(this, cclass, methodName, new Object[] { internalTransaction,
                                                                   registeredTransaction });
            throw new DuplicateTransactionException(this, internalTransaction, registeredTransaction);
        } // if(registeredTransaction != null).

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this, cclass, methodName);
    } // registerTransaction().

    /**
     * Cease to recognise the existance of an InternalTransaction involving this objectManager. Hold it ready for reuse.
     * 
     * @param internalTransaction to be deregistered.
     * @throws ObjectManagerException
     */
    protected final void deRegisterTransaction(InternalTransaction internalTransaction)
                    throws ObjectManagerException
    {
        final String methodName = "deRegisterTransaction";
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this,
                        cclass,
                        methodName,
                        new Object[] { internalTransaction });

        LogicalUnitOfWork logicalUnitOfWork = internalTransaction.getLogicalUnitOfWork();
        InternalTransaction registeredTransaction = (InternalTransaction) registeredInternalTransactions.remove(new Long(logicalUnitOfWork.identifier));

        if (registeredTransaction == null) {
            // Make the duplicate transaction useless.
            internalTransaction.terminate(Transaction.terminatedDuplicate);
            if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                trace.exit(this,
                           cclass,
                           methodName,
                           new Object[] { "via NonExistantTransactionException", logicalUnitOfWork });
            throw new NonExistentTransactionException(this,
                                                      internalTransaction);
        } // if(registeredTransaction == null).

        // Make the InternalTransaction available for reuse.
        InternalTransaction freeTransaction = (InternalTransaction) freeTransactions.put(new Long(logicalUnitOfWork.identifier),
                                                                                         internalTransaction);
        if (freeTransaction != null) {
            // Make the duplicate transaction useless.
            internalTransaction.terminate(Transaction.terminatedDuplicate);
            if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                trace.exit(this,
                           cclass,
                           methodName,
                           new Object[] { internalTransaction, freeTransaction }
                                );
            throw new DuplicateTransactionException(this,
                                                    internalTransaction,
                                                    freeTransaction);
        } // if(freeTransaction != null).
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this,
                       cclass,
                       methodName);
    } // deRegisterTransaction().

    /**
     * Notifies the ObjectManagerState that a transaction has completed all its activity
     * for one LogicalUnitOfWork. Here we decide whether or not to trigger a checkpoint.
     * 
     * @param internalTransaction which completed its work.
     * @param persistentWorkDone true is any persistent work was done.
     * @throws ObjectManagerException
     */
    protected final void transactionCompleted(InternalTransaction internalTransaction,
                                              boolean persistentWorkDone)
                    throws ObjectManagerException
    {
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this,
                        cclass,
                        "transactionCompleted",
                        new Object[] { internalTransaction, new Boolean(persistentWorkDone) });

        // Bump count of transactions.
        if (persistentWorkDone) {
            persistentTransactionsSinceLastCheckpoint++;
            // has the threshold been breached
            if (persistentTransactionsSinceLastCheckpoint > persistentTransactionsPerCheckpoint) {
                suggestCheckpoint(true);
            }
        }
        else {
            nonPersistentTransactionsSinceLastCheckpoint++;
            // has the threshold been breached 
            if (nonPersistentTransactionsSinceLastCheckpoint > nonPersistentTransactionsPerCheckpoint) {
                suggestCheckpoint(false);
            }
        } // if (persistentWorkDone)

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this,
                       cclass,
                       "transactionCompleted");
    } // transactionCompleted().

    /**
     * Delays return if we need to delay the allocation of new transactions while the checkpoint
     * helper catches up.
     * 
     * @throws ObjectManagerException
     */
    protected final void transactionPacing()
                    throws ObjectManagerException
    {
        final String methodName = "transactionPacing";
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this,
                        cclass,
                        methodName);

        // Make sure logOutput exists because during shutdown we set it to null.
        LogOutput localLogOutput = logOutput;
        if (localLogOutput == null) {
            if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                trace.exit(this, cclass, methodName, new Object[] { new Integer(state),
                                                                   stateNames[state] });
            throw new InvalidStateException(this, state, stateNames[state]);
        } // if (localLogOutput == null).

        // If the log is full, introduce a delay to allow checkpoint to run.
        // We assume that if we let the application thread run immediately it would do
        // more persistent work. This approach is better than penalising all threads, including
        // those that do non persistent work when transactions are reused or getTransaction
        // is called, however it does also penalise threads that do no more persistent work.
        // Only block transactions that can wait, ones invoked by the ckeckpointThread would block if we
        // waited for a checkpoint to complete.
        if (localLogOutput.isOcupancyHigh()) {
            if (gatherStatistics)
                transactionsDelayedForLogFull++;

            // Behave like persistent work was done.
            waitForCheckpoint(true);

//      Object lock = new Object();
//      synchronized (lock) {
//        if (Tracing.isAnyTracingEnabled() && trace.isDebugEnabled())
//          trace.debug(this,
//                     cclass,
//                     "transactionCompleted",
//                     "About to wait for "+ checkpointDelay + " milliseconds."
//                    );
//        try {
//          // Let some transactions complete.
//          // We need to wait for longer than the time it takes for a checkpoint to complete.
//          lock.wait(checkpointDelay*2);
//        } catch (InterruptedException exception) {
//          // No FFDC Code Needed.
//          ObjectManager.ffdc.processException(this,
//                                cclass,
//                                "transactionCompleted",
//                                exception,
//                                "1:2295:1.62");
//
//          if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
//            trace.exit(this,
//                       cclass,
//                       "transactionCompleted",
//                       exception);
//          throw new UnexpectedExceptionException(this,
//                                                 exception);
//        } // catch (InterruptedException exception).
//      } // synchronized (lock).
        } // if (locaLogOutput.isOcupancyHigh()).

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this,
                       cclass,
                       methodName);
    } // transactionPacing().

    /**
     * Locate a transaction registered with this objectManager. If the transaction does not already exists then create it.
     * If there is a new XID in the LogicalUnitOfWork assign it to the transaction. Only called during recovery so the
     * external Transaction returned is not registered.
     * 
     * @param logicalUnitOfWork identifying the transaction.
     * @return Transaction identified by the LogicalUnitOfWork.
     * @throws ObjectManagerException
     */
    protected final Transaction getTransaction(LogicalUnitOfWork logicalUnitOfWork)
                    throws ObjectManagerException
    {
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this,
                        cclass,
                        "getTransaction",
                        new Object[] { logicalUnitOfWork });

        InternalTransaction internalTransaction = null;
        // Should not be neccesary to synchronize as we are only called during recovery, which is single threaded.
        internalTransaction = (InternalTransaction) registeredInternalTransactions.get(new Long(logicalUnitOfWork.identifier));
        // If we found an InternalTransaction, keep its LogicalUnitOfWork and abandon the one we were given.

        if (internalTransaction == null) {
            // Have a look in the freeTransactions.
            internalTransaction = (InternalTransaction) freeTransactions.remove(new Long(logicalUnitOfWork.identifier));
            if (internalTransaction != null)
                registerTransaction(internalTransaction);
        } // if(internalTransaction == null).

        if (internalTransaction == null) {
            // Make sure we not reuse this logical unit of work identifier again.
            maximumLogicalUnitOfWorkIdentifier = Math.max(logicalUnitOfWork.identifier,
                                                          maximumLogicalUnitOfWorkIdentifier);
            // Create an InternalTransaction to use the LogicaUnitOfWork we were given.
            internalTransaction = new InternalTransaction(this,
                                                          logicalUnitOfWork);

        } else { // pre existing transaction found.
            // See if we have seen the transactions XID for the first time?
            if (logicalUnitOfWork.XID != null && internalTransaction.getXID() == null)
                // No check to see if the XID's are different.
                internalTransaction.setXID(logicalUnitOfWork.XID);
        } // if(internalTransaction == null).

        // Transaction to return.
        Transaction transaction = new Transaction(internalTransaction);
        // Not transaction = getExternalTransaction(), because this is only used internally
        // at restart by logRecords. If we used getExternalTransaction() it would make weak
        // references that would be found by the garbage collector causing it to BackOut
        // the transaction befpore recovery is completed.

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this,
                       cclass,
                       "getTransaction",
                       transaction);
        return transaction;
    } // getTransaction().

    /**
     * Locate a transaction registered with this objectManager. with the same XID as the one passed. If a null XID is
     * passed this will return any registered transaction with a null XID.
     * 
     * @param XID Xopen identifier.
     * @return Transaction identified by the XID.
     * @throws ObjectManagerException
     */
    protected final Transaction getTransactionByXID(byte[] XID)
                    throws ObjectManagerException
    {
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled()) {
            trace.entry(this,
                        cclass,
                        "getTransactionByXID");
            trace.bytes(this,
                        cclass,
                        XID);
        } // if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled()).

        Transaction externalTransaction = null; // Transaction to return.

        // Look at all registeredInternalTransactions.
        for (java.util.Iterator transactionIterator = registeredInternalTransactions.values()
                        .iterator(); transactionIterator.hasNext();) {
            InternalTransaction internalTransaction = (InternalTransaction) transactionIterator.next();
            byte[] transactionXID = internalTransaction.getXID();
            if (java.util.Arrays.equals(transactionXID,
                                        XID)) {
                externalTransaction = internalTransaction.getExternalTransaction();
                break;
            } // if (Arrays.equals(transactionsXID,XID)
        } // for... registeredInternalTransactions.

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this,
                       cclass,
                       "getTransactionByXID",
                       "returns externalTransaction=" + externalTransaction + "(Transaction)");
        return externalTransaction;
    } // End of method getTransactionByXID.

    /**
     * Create an iterator over all transactions known to this ObjectManager. The iterator returned is safe against
     * concurrent modification of the set of transactions, new transactions created after the iterator is created may not
     * be covered by the iterator.
     * 
     * @return java.util.Iterator over Transactions.
     * @throws ObjectManagerException
     */
    protected final java.util.Iterator getTransactionIterator()
                    throws ObjectManagerException
    {
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this,
                        cclass,
                        "getTransactionIterator");

        java.util.Iterator transactionIterator = new TransactionIterator();

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this,
                       cclass,
                       "getTransactionIterator",
                       transactionIterator);
        return transactionIterator;
    } // getTransactionIterator().

    /**
     * Find and complete transactions that are no longer addressable. Top up the freeTransactions pool.
     * 
     * @throws ObjectManagerException
     */
    private void completeOrphanTransactions()
                    throws ObjectManagerException
    {
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this,
                        cclass,
                        "completeOrphanTransactions");

        // Find a reference that has become unreachable,
        // because the external Transaction that owns it is itself unreachable.
        InternalTransaction.TransactionReference transactionReference = (InternalTransaction.TransactionReference) orphanTransactionsQueue.poll();
        while (transactionReference != null) {
            transactionReference.complete();
            transactionReference = (InternalTransaction.TransactionReference) orphanTransactionsQueue.poll();
        } // while( transactionReference != null).

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this,
                       cclass,
                       "completeOrphanTransactions");
    } // completeOrphanTransactions().

    /**
     * Genrates logSequenceNumber for non persistent ManagedObjects that dont write log records.
     * 
     * @return long a logSequenceNumber that is bigger than any returned so far for this run of the ObjectManager.
     * @throws ObjectManagerException
     */
    protected long getDummyLogSequenceNumber()
                    throws ObjectManagerException
    {
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this,
                        cclass,
                        "getDummyLogSequenceNumber");

        long usableLogSequenceNumber;
        // Take a lock on the log and increment the log sequence number.
        synchronized (dummyLogSequenceNumberLock) {
            dummyLogSequenceNumber++; // Set the current Sequence number.
            usableLogSequenceNumber = dummyLogSequenceNumber;
        } // synchronized (dummyLogSequenceNumberLock).

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this,
                       cclass,
                       "getDummyLogSequenceNumber",
                       new Long(usableLogSequenceNumber));
        return usableLogSequenceNumber;
    } // End of method getDummyLogSequenceNumber.

    /**
     * @return Returns the current transactionUnlockSequence.
     *         Note that this hides the getTransactionUnlockSequence() method in managedObject
     *         to give the global unlock sequence.
     */
    protected final long getGlobalTransactionUnlockSequence()
    {
        synchronized (transactionUnlockSequenceLock) {
            return transactionUnlockSequence;
        } // synchronized (transactionUnlockSequenceLock).
    }

    /**
     * Caller must be synchronized on transactionUnlockSequenceLock.
     * 
     * @return Returns the next transactionUnlockSequence.
     */
    protected final long getNewGlobalTransactionUnlockSequence()
    {
        return ++transactionUnlockSequence;
    }

    /**
     * @param idealSize the ideal Size of the ObjectManagerByteArrayOutputStream requested.
     *            The actual stream returned may have less than this bytes capacity but it can be expanded,
     *            it may have more than this capacity byt it may not be all used.
     * @return ObjectManagerByteArrayOutputStream ready for use.
     */
    final ObjectManagerByteArrayOutputStream getbyteArrayOutputStreamFromPool(int idealSize) {
        int index = (Thread.currentThread().hashCode());
        index = (index >>> 5) % byteArrayOutputStreamPools.length;
        java.util.List byteArrayOutputStreamPool = byteArrayOutputStreamPools[index];

        ObjectManagerByteArrayOutputStream byteArrayOutputStream = null;
        synchronized (byteArrayOutputStreamPool) {
            if (byteArrayOutputStreamPool.isEmpty() || idealSize > maximumByteArrayOutputStreamSize) {
                byteArrayOutputStream = new ObjectManagerByteArrayOutputStream(idealSize);
            } else {
                byteArrayOutputStream = (ObjectManagerByteArrayOutputStream) byteArrayOutputStreamPool.remove(byteArrayOutputStreamPool.size() - 1);
            } // if (byteArrayOutputStreamPool.isEmpty()).
        } // synchronized(byteArrayOutputStreamPool).
        return byteArrayOutputStream;
    } // getbyteArrayOutputStreamFromPool().

    /**
     * @param byteArrayOutputStream to be reset and reused.
     */
    final void returnByteArrayOutputStreamToPool(ObjectManagerByteArrayOutputStream byteArrayOutputStream) {
        int index = (Thread.currentThread().hashCode());
        index = (index >>> 5) % byteArrayOutputStreamPools.length;
        java.util.List byteArrayOutputStreamPool = byteArrayOutputStreamPools[index];

        // Keep small ones back for reuse, discard the large ones.
        if (byteArrayOutputStream.size() <= maximumByteArrayOutputStreamSize) {
            synchronized (byteArrayOutputStreamPool) {
                if (byteArrayOutputStreamPool.size() < byteArrayOutputStreamPoolSize) {
                    byteArrayOutputStream.reset();
                    byteArrayOutputStreamPool.add(byteArrayOutputStream);
                } // if (byteArrayOutputStreamPool.size() < byteArrayOutputStreamPoolSize).
            } // synchronized (byteArrayOutputStreamPool).
        } // if (byteArrayOutputStream.size() < maximumByteArrayOutputStreamSize).
    } // returnByteArrayOutputStreamToPool.

    /*
     * Builds a set of properties containing the current statistics. @return java.util.Map the statistics.
     */
    protected java.util.Map captureStatistics()
    {
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this,
                        cclass,
                        "captureStatistics");

        java.util.Map statistics = new java.util.HashMap();

        statistics.put("totalCheckpointsTaken",
                       Long.toString(totalCheckpointsTaken));
        statistics.put("waitingBetweenCheckpointsMilliseconds",
                       Long.toString(waitingBetweenCheckpointsMilliseconds));
        statistics.put("flushingCheckpointStartMilliseconds",
                       Long.toString(flushingCheckpointStartMilliseconds));
        statistics.put("pausedDuringCheckpointMilliseconds",
                       Long.toString(pausedDuringCheckpointMilliseconds));
        statistics.put("flushingObjectStoresForCheckpointMilliseconds",
                       Long.toString(flushingObjectStoresForCheckpointMilliseconds));
        statistics.put("flushingEndCheckpointMilliseconds",
                       Long.toString(flushingEndCheckpointMilliseconds));
        statistics.put("threadsWaitingForCheckpoint",
                       Integer.toString(checkpointHelper.threadsWaitingForCheckpoint));
        statistics.put("currentMaximumActiveTransactions",
                       Long.toString(currentMaximumActiveTransactions));
        statistics.put("registeredInternalTransactions.size()",
                       Integer.toString(registeredInternalTransactions.size()));
        statistics.put("freeTransactions.size()",
                       Integer.toString(freeTransactions.size()));
        statistics.put("totalTransactions",
                       Long.toString(totalTransactions));
        statistics.put("reusedTransactions",
                       Long.toString(reusedTransactions));
        statistics.put("totalTransactionsRequiringCheckpoint",
                       Long.toString(totalTransactionsRequiringCheckpoint));
        statistics.put("maximumTransactionsInAnyCheckpoint",
                       Long.toString(maximumTransactionsInAnyCheckpoint));
        statistics.put("transactionsDelaydForLogFull",
                       Long.toString(transactionsDelayedForLogFull));
        int byteArrayOutputStreamPoolsSize = 0;
        for (int i = 0; i < byteArrayOutputStreamPools.length; i++)
            byteArrayOutputStreamPoolsSize = byteArrayOutputStreamPoolsSize + byteArrayOutputStreamPools[i].size();
        statistics.put("byteArrayOutputStreamPoolsSize",
                       Integer.toString(byteArrayOutputStreamPoolsSize));

        totalCheckpointsTaken = 0;
        waitingBetweenCheckpointsMilliseconds = 0;
        flushingCheckpointStartMilliseconds = 0;
        pausedDuringCheckpointMilliseconds = 0;
        flushingObjectStoresForCheckpointMilliseconds = 0;
        flushingEndCheckpointMilliseconds = 0;
        reusedTransactions = 0;
        totalTransactionsRequiringCheckpoint = 0;
        maximumTransactionsInAnyCheckpoint = 0;
        transactionsDelayedForLogFull = 0;

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this,
                       cclass,
                       "captureStatistics",
                       statistics);
        return statistics;
    } // method captureStatistics().

    /*
     * @returns int the current state for the ObjectManagerState.
     */
    protected int getObjectManagerStateState()
    {
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this,
                        cclass,
                        "getState");

        int stateToReturn = state;

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this,
                       cclass,
                       "getState",
                       stateToReturn + " " + ObjectManagerState.stateNames[stateToReturn]);
        return stateToReturn;
    } // method getObjectManagerStateState().

    /**
     * Makes a state transition. Call must be single threaded through this.
     * 
     * @param nextState the map of the next state.
     * @throws ObjectManagerException
     */
    void setState(int[] nextState)
                    throws ObjectManagerException
    {
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this,
                        cclass,
                        "setState",
                        new Object[] { nextState,
                                      new Integer(state),
                                      stateNames[state] });

        previousState = state; // Capture the previous state for dump.
        state = nextState[state]; // Make the state change.

        if (state == stateError) {
            StateErrorException stateErrorException = new StateErrorException(this,
                                                                              previousState,
                                                                              stateNames[previousState]);
            ObjectManager.ffdc.processException(this,
                                                cclass,
                                                "setState",
                                                stateErrorException,
                                                "1:2674:1.62");

            if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                trace.exit(this,
                           cclass,
                           "setState",
                           new Object[] { stateErrorException,
                                         new Integer(state),
                                         stateNames[state] });
            throw stateErrorException;
        } // if (state == stateError).

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this,
                       cclass,
                       "setState",
                       new Object[] { new Integer(state),
                                     stateNames[state] });
    } // setState().

    // --------------------------------------------------------------------------
    // extends ManagedObject.
    // --------------------------------------------------------------------------

    /**
     * Replace the state of this object with the same object in some other state. Used for to restore the before image if
     * a transaction rolls back or is read from the log during restart.
     * 
     * @param other is the object this object is to become a clone of.
     * @throws ObjectManagerException
     */
    public void becomeCloneOf(ManagedObject other)
                    throws ObjectManagerException {
        final String methodName = "becomeCloneOf";
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this, cclass, methodName, other);

        ObjectManagerState otherObjectManagerState = (ObjectManagerState) other;

        maximumObjectStoreIdentifier = otherObjectManagerState.maximumObjectStoreIdentifier;
        persistentTransactionsPerCheckpoint = otherObjectManagerState.persistentTransactionsPerCheckpoint;
        nonPersistentTransactionsPerCheckpoint = otherObjectManagerState.nonPersistentTransactionsPerCheckpoint;
        logFullTriggerCheckpointThreshold = otherObjectManagerState.logFullTriggerCheckpointThreshold;
        logFullPostCheckpointThreshold = otherObjectManagerState.logFullPostCheckpointThreshold;
        maximumActiveTransactions = otherObjectManagerState.maximumActiveTransactions;
        checkpointDelay = otherObjectManagerState.checkpointDelay;
        coldStartLogFileName = otherObjectManagerState.coldStartLogFileName;
        coldStartTime = otherObjectManagerState.coldStartTime;

        if (mainObjectManagerState) {
            synchronized (objectStores) {
                mergeObjectStores(otherObjectManagerState);
                setDefinitiveNamedObjects();
            }
        } else
            objectStores = otherObjectManagerState.objectStores;

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this, cclass, methodName);
    } // becomeCloneOf().

    /**
     * Merge the otherObjectManagerState.objectStores with our own.
     * Caller must be synchronized on objecStores.
     * 
     * 1) New unknown object stores are opend and added to the known objectStores set. 2) Existing oobjectStores are
     * retained, and not replaced with the new one, this allows apps to continue using the ones they may already have
     * reference to. 3) ObjectStores not present in the new set are closed and removed from the objectStores set.
     * 
     * @param otherObjectManagerState
     * @throws ObjectManagerException
     */
    private void mergeObjectStores(ObjectManagerState otherObjectManagerState)
                    throws ObjectManagerException
    {
        // Merge the other ObjectStores, with those already active in this ObjectManagerState.
        // Make sure we have all of the new ObjectStores.
        for (java.util.Iterator objectStoreIterator = otherObjectManagerState.objectStores.values().iterator(); objectStoreIterator.hasNext();) {
            ObjectStore objectStore = (ObjectStore) objectStoreIterator.next();
            // We cannot use objectManagerState.getObjectStore,
            // because it throws NonExistantObjectStoreException.
            Object existingStore = objectStores.get(new Integer(objectStore.getIdentifier()));
            if (existingStore == null) {
                objectStore.open(this);
                objectStores.put(new Integer(objectStore.getIdentifier()),
                                 objectStore);

                // Does the store contain a the definitive copy of the namedObjects Tree?
                if (objectStore.getContainsRestartData()
                    && namedObjects == null) {
                    // We do not need to create the tree if it does not exist because the original transaction
                    // will have taken care of that.
                    Token namedObjectsToken = new Token(objectStore,
                                                        ObjectStore.namedObjectTreeIdentifier.longValue());
                    // Swap for the definitive Token, if there is one.
                    namedObjectsToken = objectStore.like(namedObjectsToken);

                } // if (objectStore.getContainsRestartData())...
            } // if (existingStore == null).
        } // for otherObjectManagerstate.objectStores...

        // Remove any ObjectStores in this objectStores but not in the otherObjectManagerState.objectStores.
        for (java.util.Iterator objectStoreIterator = objectStores.values().iterator(); objectStoreIterator.hasNext();) {
            ObjectStore objectStore = (ObjectStore) objectStoreIterator.next();
            // We cannot use objectManagerState.getObjectStore,
            // because it throws NonExistantObjectStoreException.
            Object newObjectStore = otherObjectManagerState.objectStores.get(new Integer(objectStore.getIdentifier()));
            if (newObjectStore == null) {
                objectStore.close();
                objectStores.remove(new Integer(objectStore.getIdentifier()));
                // No need to modify the namedObjects Tree as that is taken care of by the rest of the transaction.

                // See if the ObjectStore contains the nameObjects Tree?
                if (namedObjects != null) {
                    if (namedObjects.getObjectStore() == objectStore) {
                        namedObjects = null;
                    } // if (namedObjects.getObjectStore()...
                } // if (namedObjects != null).

            } // if (existingStore == null).
        } // for otherObjectManagerstate.objectStores...

        // It is now safe to restore tokens which make reference to their ObjectStores.

    } // mergeObjectStores().

    // --------------------------------------------------------------------------
    // Simplified serialization.
    // --------------------------------------------------------------------------

    /**
     * No argument constructor.
     * 
     * @exception ObjectManagerException
     */
    ObjectManagerState()
        throws ObjectManagerException
    {
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this,
                        cclass,
                        "<init>");

        // We are the not the real state, just a copy as yet.
        mainObjectManagerState = false;

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this,
                       cclass,
                       "<init>");
    } // ObjectManagerState().

    private static final byte simpleSerialVersion = 0;

    /*
     * (non-Javadoc)
     * 
     * @see int SimplifiedSerialization.getSignature()
     */
    protected int getSignature()
    {
        return signature_ObjectManagerState;
    } // getSignature().

    /*
     * (non-Javadoc)
     * 
     * @see com.ibm.ws.objectManager.SimplifiedSerialization#estimatedLength()
     */
    public long estimatedLength() {
        return serializedSize;
    }

    /*
     * (non-Javadoc)
     * 
     * @see SimplifiedSerialization.writeObject(java.io.DataInputStream)
     */
    public void writeObject(java.io.DataOutputStream dataOutputStream)
                    throws ObjectManagerException {
        final String methodName = "writeObject";
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this, cclass, methodName, dataOutputStream);

        try {
            dataOutputStream.writeByte(simpleSerialVersion);
            super.writeObject(dataOutputStream);

            // ObjectStores are serialized first because any references to ManagedObjects will
            // indirectly refer to them.
            //TODO Make ObjecStores managedObjects, store them individually in the restartObjectStores!
            //TODO This lets them use simpleSerialization and any admin changes are transactional.
            java.io.ObjectOutputStream objectOutputStream = new java.io.ObjectOutputStream(dataOutputStream);
            synchronized (objectStores) {
                objectOutputStream.writeObject(objectStores);
            }
            objectOutputStream.close();

            dataOutputStream.writeLong(maximumObjectStoreIdentifier);
            dataOutputStream.writeLong(persistentTransactionsPerCheckpoint);
            dataOutputStream.writeLong(nonPersistentTransactionsPerCheckpoint);
            dataOutputStream.writeFloat(logFullTriggerCheckpointThreshold);
            dataOutputStream.writeFloat(logFullPostCheckpointThreshold);
            dataOutputStream.writeLong(maximumActiveTransactions);
            dataOutputStream.writeInt(checkpointDelay);
            dataOutputStream.writeUTF(coldStartLogFileName);
            dataOutputStream.writeLong(coldStartTime);
            // Note the serialized size ready for the next time we serialize.
            serializedSize = dataOutputStream.size();

        } catch (java.io.IOException exception) {
            // No FFDC Code Needed.
            ObjectManager.ffdc.processException(this, cclass, methodName, exception, "1:2887:1.62");

            if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                trace.exit(this, cclass, methodName, exception);
            throw new PermanentIOException(this,
                                           exception);
        } // catch (java.io.IOException exception).

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this, cclass, methodName);
    } // writeObject().

    /*
     * (non-Javadoc)
     * 
     * @see SimplifiedSerialization.readObject(java.io.DataInputStream,ObjectManagerState)
     */
    public void readObject(java.io.DataInputStream dataInputStream,
                           ObjectManagerState objectManagerState)
                    throws ObjectManagerException {
        final String methodName = "readObject";
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this,
                        cclass,
                        methodName,
                        new Object[] { dataInputStream,
                                      objectManagerState });

        try {
            byte version = dataInputStream.readByte();
            if (Tracing.isAnyTracingEnabled() && trace.isDebugEnabled())
                trace.debug(this,
                            cclass,
                            methodName,
                            new Byte(version));
            super.readObject(dataInputStream,
                             objectManagerState);

            // There is no transient data in either SingleFileObjectStore or SingleNonNioFileObjectStore, 
            // and the two disk formats are identical. Hence we can flip between the two types of store
            // according to whether we are running on an Nio capable JVM or not.
            // PK73292.1
            // Disable this migration code by default. Allow it to be toggled via a compile
            // time flag.
            java.io.ObjectInputStream objectInputStream;

            if (migrateObjectStores)
            {
                objectInputStream = new java.io.ObjectInputStream(dataInputStream)
                {
                    /*
                     * (non-Javadoc)
                     * 
                     * @see java.io.ObjectInputStream#readClassDescriptor()
                     */
                    protected java.io.ObjectStreamClass readClassDescriptor() throws java.io.IOException, java.lang.ClassNotFoundException
                    {
                        final String methodName = "readClassDescriptor";

                        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                            trace.entry(this, cclass, methodName);

                        java.io.ObjectStreamClass objectStreamClass = super.readClassDescriptor();
                        if (objectStreamClass.getName().equals("com.ibm.ws.objectManager.SingleFileObjectStore")
                            && !nioAvailable)
                        {
                            if (Tracing.isAnyTracingEnabled() && trace.isDebugEnabled())
                                trace.debug(this, cclass, methodName, new Object[] { "Migrating:2950", objectStreamClass });

                            // PK73292
                            // use Class.forName() to delay class loading of object store 
                            // implementation until this code path is taken.
                            objectStreamClass = java.io.ObjectStreamClass.lookup(Class.forName("com.ibm.ws.objectManager.SingleNonNioFileObjectStore"));
                        }
                        else if (objectStreamClass.getName().equals("com.ibm.ws.objectManager.SingleNonNioFileObjectStore")
                                 && nioAvailable)
                        {
                            if (Tracing.isAnyTracingEnabled() && trace.isDebugEnabled())
                                trace.debug(this, cclass, methodName, new Object[] { "Migrating:2960", objectStreamClass });

                            // PK73292
                            // use Class.forName() to delay class loading of object store 
                            // implementation until this code path is taken.
                            objectStreamClass = java.io.ObjectStreamClass.lookup(Class.forName("com.ibm.ws.objectManager.SingleFileObjectStore"));
                        } // if (   objectStreamClass.getName().

                        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                            trace.exit(this, cclass, methodName, new Object[] { objectStreamClass });
                        return objectStreamClass;
                    } // readClassDescriptor().
                };
            }
            else
            {
                objectInputStream = new java.io.ObjectInputStream(dataInputStream);
            }

            objectStores = (java.util.Map) objectInputStream.readObject();
            objectInputStream.close();

            // ObjectStores are merged in becomeCloneOf().

            maximumObjectStoreIdentifier = dataInputStream.readLong();
            persistentTransactionsPerCheckpoint = dataInputStream.readLong();
            nonPersistentTransactionsPerCheckpoint = dataInputStream.readLong();
            logFullTriggerCheckpointThreshold = dataInputStream.readFloat();
            logFullPostCheckpointThreshold = dataInputStream.readFloat();
            maximumActiveTransactions = dataInputStream.readLong();
            checkpointDelay = dataInputStream.readInt();
            coldStartLogFileName = dataInputStream.readUTF();
            dataInputStream.readLong();

        } catch (java.io.IOException exception) {
            // No FFDC Code Needed.
            ObjectManager.ffdc.processException(this,
                                                cclass,
                                                methodName,
                                                exception,
                                                "1:2999:1.62");

            if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                trace.exit(this,
                           cclass,
                           methodName,
                           new Object[] { "PermanentIOException:%C", exception });
            throw new PermanentIOException(this,
                                           exception);

        } catch (java.lang.ClassNotFoundException exception) {
            // No FFDC Code Needed.
            ObjectManager.ffdc.processException(this,
                                                cclass,
                                                methodName,
                                                exception,
                                                "1:3015:1.62");

            if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                trace.exit(this,
                           cclass,
                           methodName,
                           new Object[] { "ClassNotFoundException:3021", exception });
            throw new com.ibm.ws.objectManager.ClassNotFoundException(this, exception);

        } // catch (java.io.IOException exception).

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this,
                       cclass,
                       methodName);
    } // readObject().

    void registerEventCallback(ObjectManagerEventCallback callback) {
        final String methodName = "registerEventCallback";
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this, cclass, methodName, callback);

        synchronized (callbacks) {
            callbacks.add(callback);
        }

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this, cclass, methodName);
    } // registerEventCallback().

    void notifyCallbacks(int event, Object[] args) {
        final String methodName = "notifyCallbacks";
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this, cclass, methodName, new Object[] { new Integer(event), args });

        synchronized (callbacks) {
            for (java.util.Iterator iterator = callbacks.iterator(); iterator.hasNext();) {
                ObjectManagerEventCallback callback = (ObjectManagerEventCallback) iterator.next();
                callback.notification(event, args);
            } // for.        
        } // synchronized (callbacks).

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this, cclass, methodName);
    } // notifyCallbacks.

    /*
     * Check to see if we are in shutdown mode. This will true if we are
     * either in 'shutdown started' or 'stopped'.
     */
    protected boolean inShutdown() throws ObjectManagerException
    {
        if (getObjectManagerStateState() == stateShutdownStarted ||
            getObjectManagerStateState() == stateStopped)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    //--------------------------------------------------------------------------
    // extends Object.
    // --------------------------------------------------------------------------

    /*
     * (non-Javadoc)
     * 
     * @see java.lang.Object#toString()
     */
    public String toString()
    {
        return new String("ObjectManagerState"
                          + "(" + logFileName + ")"
                          + "/" + stateNames[state]
                          + " " + super.toString());
    } // toString().

    // ----------------------------------------------------------------------------------------------
    // Inner classes
    // ----------------------------------------------------------------------------------------------

    /*
     * 
     * @author Andrew_Banks
     * 
     * Gives up an ExternalTransaction covering the next InternalTransaction.
     */
    private class TransactionIterator
                    implements java.util.Iterator
    {
        java.util.Iterator internalTransactionIterator;

        TransactionIterator()
        {
            internalTransactionIterator = registeredInternalTransactions.values()
                            .iterator();
        }

        public boolean hasNext()
        {
            return internalTransactionIterator.hasNext();
        }

        public Object next()
        {
            InternalTransaction internalTransaction = (InternalTransaction) internalTransactionIterator.next();
            Transaction transaction = internalTransaction.getExternalTransaction();
            return transaction;
        }

        public void remove()
        {
            throw new UnsupportedOperationException();
        }
    } // inner class TransactionIterator .

    /**
     * The worker thread that executes a checkpoint.
     */
    protected class CheckpointHelper
                    implements Runnable
    {
        private boolean running = true; // True if we are not finished.
        private boolean waiting = false; // True if waiting.
        private boolean checkpointRequested = false; // True if a checkpoint is requested.
        private boolean persistentTransactions = false; // True is persitent work is t be checkpointed.
        private Exception abnormalTerminationException = null;
        private long checkpointCycle = 0; // Identifies the checkpoint.
        protected Thread checkpointThread = null;
        private int threadsWaitingForCheckpoint = 0;

        /**
         * Constructor
         * 
         * @throws ObjectManagerException
         */
        CheckpointHelper()
            throws ObjectManagerException
        {
            if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                trace.entry(this,
                            cclass,
                            "<init>");

            checkpointThread = new Thread(this);

            checkpointThread.setName("CheckpointHelper");
            // Run the CheckpointHelper in preference to other threads.
            checkpointThread.setPriority(Thread.NORM_PRIORITY + 1);
            // checkpointThread.setPriority(Thread.MAX_PRIORITY);

            // synchronize to make sure the CheckpointHelper starts before
            // any requests are admited.
            synchronized (this) {
                checkpointThread.start();
                try {
                    wait();
                } catch (InterruptedException exception) {
                    // No FFDC Code Needed.
                    ObjectManager.ffdc.processException(this,
                                                        cclass,
                                                        "waitForCheckpoint",
                                                        exception,
                                                        "1:3180:1.62");

                    if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                        trace.exit(this,
                                   cclass,
                                   "waitForCheckpoint",
                                   exception);
                    throw new UnexpectedExceptionException(this,
                                                           exception);

                } // catch (InterruptedException exception).
            } // synchronized (this).

            if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                trace.exit(this,
                           cclass,
                           "<init>");
        } // CheckpointHelper().

        // ----------------------------------------------------------------------------------------------
        // implements runnable
        // ----------------------------------------------------------------------------------------------

        public void run()
        {
            if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                trace.entry(this,
                            cclass,
                            "run");

            // Outer try/catch block treats all unexpected errors as terminal
            // and shuts down the Objectmanager if any occur.
            try {
                for (;;) {
                    boolean nextCheckpointPersistentence;
                    synchronized (this) {
                        checkpointCycle++; // Move on to the next cycle.
                        notifyAll(); // Release threads waiting for the checkpoint.
                        threadsWaitingForCheckpoint = 0;

                        if (!running)
                            break;

                        if (!checkpointRequested) { // Should we wait?
                            waiting = true;
                            // InterruptedException is caught by the outer try/catch block.
                            wait();
                            waiting = false;
                        } // if (!checkpointRequested).
                        checkpointRequested = false;
                        nextCheckpointPersistentence = persistentTransactions;
                        persistentTransactions = false;
                    } // synchronized (this).

                    // Perform the checkpoint while not synchronized, this allows new requests
                    // to be made without blocking.
                    // ObjectmanagerdException is caught by the outer try/catch block.
                    if (running) // We might have just shutdown.
                        performCheckpoint(nextCheckpointPersistentence); // Perform the checkpoint.

                } // for (;;).
            } catch (Exception exception) {
                // No FFDC Code Needed.
                ObjectManager.ffdc.processException(this,
                                                    cclass,
                                                    "run",
                                                    exception,
                                                    "1:3247:1.62");

                running = false;
                abnormalTerminationException = exception;
                // Make one asynchronous request to shutdown the ObjectManager.
                requestShutdown();
                synchronized (this) {
                    // We are shutting down now so notify all. The abnormalexception
                    // has been set so this should indicate to the caller that the
                    // checkpoint did fail.
                    notifyAll();
                } // synchronized (this).
            } // catch (ObjectManagerException exception).

            if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                trace.exit(this,
                           cclass,
                           "run");
        } // run().

        /**
         * A non blocking request that a checkpoint should be performed.
         * Will return before the checkpoint is complete.
         * 
         * @param persistent true if persistent transactions are to be checkpointed.
         * @throws ObjectManagerException
         */
        synchronized void requestCheckpoint(boolean persistent)
                        throws ObjectManagerException
        {
            if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                trace.entry(this,
                            cclass,
                            "requestCheckpoint",
                            new Object[] { new Boolean(persistent) });

            // Has something previously gone wrong?
            if (abnormalTerminationException != null) {
                if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                    trace.exit(this,
                               cclass,
                               "requestCheckpoint",
                               abnormalTerminationException);
                throw new UnexpectedExceptionException(this,
                                                       abnormalTerminationException);
            } // if (abnormalTerminationException != null).
              // Any request arriving after we have stopped running, at shutdown will not be honoured.
            checkpointRequested = true;
            persistentTransactions = persistentTransactions || persistent;
            if (waiting) {
                notify();
            } // if (waiting).

            if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                trace.exit(this,
                           cclass,
                           "requestCheckpoint");
        } // requestCheckpoint().

        /**
         * A non blocking suggestion that a checkpoint should be performed.
         * Will return before the checkpoint is complete.
         * This is different to requestCheckpoint in that it will only trigger a checkpoint
         * if the checkpointer helper is not already running (if it is sleeping). This is
         * useful to avoid a double checkpoint when the checkpoint is triggered by occupancy
         * or number of transactions.
         * 
         * A small window exists in which callers could really mean that a checkpoint should
         * run based on up-to-date numbers. So callers of this method should not rely on the
         * fact that a checkpoint will happen as a result of this call, in addition to any
         * that is currently in progress. Callers requiring this should use requestCheckpoint
         * or waitForCheckpoint.
         * 
         * It always updates persistentTransactions if appropriate.
         * 
         * @param persistent true if persistent transactions are to be checkpointed.
         * @throws ObjectManagerException
         */
        synchronized void suggestCheckpoint(boolean persistent)
                        throws ObjectManagerException
        {
            if (trace.isEntryEnabled())
                trace.entry(this,
                            cclass,
                            "suggestCheckpoint",
                            new Object[] { new Boolean(persistent) });

            // Has something previously gone wrong?
            if (abnormalTerminationException != null) {
                if (trace.isEntryEnabled())
                    trace.exit(this,
                               cclass,
                               "requestCheckpoint",
                               abnormalTerminationException);
                throw new UnexpectedExceptionException(this,
                                                       abnormalTerminationException);
            } // if (abnormalTerminationException != null).

            // Any request arriving after we have stopped running, at shutdown will not be honoured.
            persistentTransactions = persistentTransactions || persistent;
            if (waiting) {
                checkpointRequested = true;
                notify();
            } // if (waiting).

            if (trace.isEntryEnabled())
                trace.exit(this,
                           cclass,
                           "suggestCheckpoint");
        } // suggestCheckpoint().

        /**
         * A blocking call to checkpoint, returns when checkpoint is complete.
         * 
         * @param persistent true if persisent state is to be checkpointed.
         * @throws ObjectManagerException
         */
        private synchronized void waitForCheckpoint(boolean persistent)
                        throws ObjectManagerException
        {
            if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                trace.entry(this,
                            cclass,
                            "waitForCheckpoint",
                            new Boolean(persistent));

            long endCycle;
            if (waiting) {
                // Currently inactive so wait for then next checkpoint.
                endCycle = checkpointCycle;
            } else {
                // Currently checkpointing, wait for another checkpoint after this one finishes.
                endCycle = checkpointCycle + 1;
            } // if (waiting).

            while (endCycle >= checkpointCycle
                   && abnormalTerminationException == null) {
                requestCheckpoint(persistent);
                threadsWaitingForCheckpoint++;
                try {
                    wait();
                } catch (InterruptedException exception) {
                    // No FFDC Code Needed.
                    ObjectManager.ffdc.processException(this,
                                                        cclass,
                                                        "waitForCheckpoint",
                                                        exception,
                                                        "1:3393:1.62");

                    if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                        trace.exit(this,
                                   cclass,
                                   "waitForCheckpoint",
                                   exception);
                    throw new UnexpectedExceptionException(this,
                                                           exception);

                } // catch (InterruptedException exception).
            } // while (startCycle == checkpointCycle).

            // Was there a happy ending?
            if (abnormalTerminationException != null) {
                if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                    trace.exit(this,
                               cclass,
                               "waitForCheckpoint",
                               abnormalTerminationException);
                throw new UnexpectedExceptionException(this,
                                                       abnormalTerminationException);
            } // if (abnormalTerminationException != null).

            if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                trace.exit(this,
                           cclass,
                           "waitForCheckpoint");
        } // waitForCheckpoint().

        /*
         * Terminate the CheckpointHelper.
         */
        void shutdown()
                        throws ObjectManagerException
        {
            if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                trace.entry(this,
                            cclass,
                            "shutdown");

            synchronized (this) {
                running = false;

                if (waiting)
                    notify();
            } // synchronize (this).

            // Wait for the worker thread to complete.
            try {
                checkpointThread.join();
            } catch (InterruptedException exception) {
                // No FFDC Code Needed.
                ObjectManager.ffdc.processException(this,
                                                    cclass,
                                                    "shutdown",
                                                    exception,
                                                    "1:3450:1.62");

                if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                    trace.exit(this,
                               cclass,
                               "shutdown",
                               exception);
                throw new UnexpectedExceptionException(this,
                                                       exception);
            } // catch (InterruptedException exception).

            if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                trace.exit(this,
                           cclass,
                           "shutdown");
        } // shutdown().
    } // checkpointHelper().

    /**
     * Handles asynchronous requests to shut down the ObjectManager.
     */
    private class ShutdownHelper
                    implements Runnable
    {
        /**
         * Constructor
         */
        ShutdownHelper()
        {
            if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                trace.entry(this,
                            cclass,
                            "<init>");

            Thread shutdownThread = new Thread(this);
            shutdownThread.setName("ShutdownHelper");
            shutdownThread.start();

            if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                trace.exit(this,
                           cclass,
                           "<init>");
        } // ShutdownHelper().

        // ---------------------------------------------------------------------------------
        // implements Runnable.
        // ---------------------------------------------------------------------------------
        public void run() {
            final String methodName = "run";
            if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                trace.entry(this,
                            cclass,
                            methodName);
            // Make one attempt to shutdown, if anything goes wrong just report the problem
            // but dont attempt any recovery. If we are here it will be because something
            // unexpected has happened and we don't want to make things any worse.
            try {
                // Use ShutdownFast because any attempt to backout Transactions or take a
                // Checkpoint is likely to fail.
                shutdownFast();
            } catch (Exception exception) {
                // No FFDC Code Needed.
                ObjectManager.ffdc.processException(this,
                                                    cclass,
                                                    methodName,
                                                    exception,
                                                    "1:3516:1.62");

            } // catch (InterruptedException exception).

            if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                trace.exit(this,
                           cclass,
                           methodName);
        } // run().
    } // inner class shutdownHelper().
}
780785
final public void close() {
		List<C> connsToClose;
		synchronized(poolLock) {
			// Prevent any new connections
			isClosed = true;
			// Find any connections that are available and open
			connsToClose = new ArrayList<>(availableConnections.size());
			for(PooledConnection<C> availableConnection : availableConnections) {
				synchronized(availableConnection) {
					C conn = availableConnection.connection;
					if(conn!=null) {
						availableConnection.connection = null;
						connsToClose.add(conn);
					}
				}
			}
			poolLock.notifyAll();
		}
		// Close all of the connections
		for(C conn : connsToClose) {
			try {
				close(conn);
			} catch(Exception err) {
				logger.log(Level.WARNING, null, err);
			}
		}
	}
4546
void stopAll() {

		try {
			this.dmClient.closeConnection();
			stop();

		} catch( Throwable t ) {
			this.logger.warning( "An error occurred while closing the connection of the DM client." );
			Utils.logException( this.logger, new RuntimeException( t ));
		}
	}