Called to perform recovery action during a warm start of the ObjectManager.

@param objectManagerState of the ObjectManager performing recovery.
@throws ObjectManagerException
350815
public void performRecovery(ObjectManagerState objectManagerState)
                    throws ObjectManagerException
    {
        final String methodName = "performRecovery";
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this,
                        cclass,
                        methodName,
                        new Object[] { objectManagerState,
                                      logicalUnitOfWork,
                                      new Integer(transactionState),
                                      token,
                                      new Integer(managedObjectBytes.length) });

        // Recover the ManagedObject from its serialized bytes.
        ManagedObject replacementManagedObject = ManagedObject.restoreFromSerializedBytes(managedObjectBytes,
                                                                                          objectManagerState);

        // Replace the object using its original transaction.
        Transaction transactionForRecovery = objectManagerState.getTransaction(logicalUnitOfWork);
        ManagedObject existingManagedObject = token.getManagedObject();
        if (existingManagedObject == null) {
            // The object may have already been deleted from the ObjectStore,
            // so create a dummy object to keep the transaction happy.
            // The Token will have the ObjecStore and storedObjectIdentifier so the the correct delete in the
            // ObjectStore can take place.
            DummyManagedObject dummyManagedObject = new DummyManagedObject("Created by TransactionReplaceLogRecord.performRecovery()");
            dummyManagedObject.state = ManagedObject.stateReady;
            dummyManagedObject.owningToken = token;
            existingManagedObject = token.setManagedObject(dummyManagedObject);
            existingManagedObject.state = ManagedObject.stateReady;
        } // if(existingManagedObject == null).

        transactionForRecovery.lock(existingManagedObject);
        token.setManagedObject(replacementManagedObject); // Revert to the restored managed object.

        transactionForRecovery.replace(existingManagedObject); // Redo the replace.
        // No need to reset the transaction state because Replace can only be executed before
        // the transaction is prepared.
        // transactionForRecovery.internalTransaction.resetState(transactionState);

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this,
                       cclass,
                       methodName);
    }
292568
public synchronized void setCachedManagedObjectsSize(int cachedManagedObjectsSize)
                    throws ObjectManagerException
    {
        this.cachedManagedObjectsSize = cachedManagedObjectsSize;
        cachedManagedObjects = new java.lang.ref.SoftReference[cachedManagedObjectsSize];
        writeHeader();
        force();
    }
942249
public void onRestoreInstanceState(Bundle presenterState) {
        if (presenter != null)
            throw new IllegalArgumentException("onRestoreInstanceState() should be called before onResume()");
        this.bundle = ParcelFn.unmarshall(ParcelFn.marshall(presenterState));
    }
150290
public synchronized void open(ObjectManagerState objectManagerState)
                    throws ObjectManagerException
    {
        final String methodName = "open";
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this, cclass,
                        methodName,
                        new Object[] { objectManagerState });

        super.open(objectManagerState);

        managedObjectsOnDisk = new java.util.HashSet();
        managedObjectsToWrite = new ConcurrentHashMap(concurrency);
        tokensToDelete = new ConcurrentHashMap(concurrency);

        storeDirectoryName = (String) objectManagerState.objectStoreLocations.get(storeName);
        if (storeDirectoryName == null)
            storeDirectoryName = storeName;
        if (Tracing.isAnyTracingEnabled() && trace.isDebugEnabled())
            trace.debug(this,
                        cclass,
                        methodName,
                        new Object[] { "storeName:150", storeName, storeDirectoryName });

        // During restart the file directory must exist.
        // This test a voids creating unnecessary empty files in the case where the file does not already 
        // exist at a warm start. It is not foolproof though, if the file is deleted by another process
        // between here and the RandomAccesFile constructor we will create a new empty file.    
        if (objectManagerState.getObjectManagerStateState() == ObjectManagerState.stateReplayingLog
            && !(new java.io.File(storeDirectoryName).exists())) {
            if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                trace.exit(this, cclass, methodName, new Object[] { "File does not exist:159" });
            throw new NonExistentObjectStoreFileException(this,
                                                          storeDirectoryName);
        } // if.

        // Make the directory to write the objects to.
        java.io.File storeDirectory = new java.io.File(storeDirectoryName);
        if (!(storeDirectory.isDirectory())) {
            storeDirectory.mkdirs();
        } // if (!(storeDirectory.isDirectory())).

        // Now look at the header file and initialise the ObjectStore.
        try {
            String storedHeaderFileName = storeDirectoryName + java.io.File.separator + headerIdentifier;
            java.io.RandomAccessFile headerFile = new java.io.RandomAccessFile(storedHeaderFileName,
                                                                               "r");
            int versionRead = headerFile.readInt();
            long objectStoreIdentifierRead = headerFile.readLong();
            if (Tracing.isAnyTracingEnabled() && trace.isDebugEnabled())
                trace.debug(this,
                            cclass,
                            "open",
                            new Object[] { new Integer(versionRead),
                                          new Long(objectStoreIdentifierRead) });
            // Use the saved value if we are a new store.
            if (objectStoreIdentifier == IDENTIFIER_NOT_SET)
                objectStoreIdentifier = (int) objectStoreIdentifierRead;

            sequenceNumber = headerFile.readLong();
            if (Tracing.isAnyTracingEnabled() && trace.isDebugEnabled())
                trace.debug(this,
                            cclass,
                            "open",
                            new Object[] { new Long(sequenceNumber) });

        } catch (java.io.FileNotFoundException exception) {
            // The file does not exist.
            // No FFDC Code Needed, this may be first use of a store.
            if (Tracing.isAnyTracingEnabled() && trace.isEventEnabled())
                trace.event(this,
                            cclass,
                            "java.io.FileNotFoundException caught opening header",
                            exception);

            // Set initial values.      

            // Sequence numbers 0-200 are reserved.    
            sequenceNumber = initialSequenceNumber;

            writeHeader();

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

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

        // Are we interested in what's already on the disk?
        if (storeStrategy == STRATEGY_KEEP_UNTIL_NEXT_OPEN) {
            clear();
        } // if storeStrategy...

        // Find the next store sequence number that we can use.
        // Do this by searching the store.
        String ExistingFiles[]; // Array of existing file names.
        ExistingFiles = storeDirectory.list();
        synchronized (inMemoryTokens) {
            for (int iFile = 0; // Index to existing files.
            iFile < ExistingFiles.length; iFile++) {
                sequenceNumber = Math.max((new Long(ExistingFiles[iFile])).longValue(),
                                          sequenceNumber);
                managedObjectsOnDisk.add(new Long(ExistingFiles[iFile]));
            } // for loop over existing Files.
        } // synchronized (inMemoryTokens).

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this, cclass,
                       "open");
    }
71744
protected synchronized void shutdown()
                    throws ObjectManagerException
    {
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this, cclass
                        , "shutDown"
                            );

        setState(nextStateForShutdown);
        // Any attempt by any therad to do anything with this Transaction
        // from now on will result in a InvalidStateException.

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this, cclass
                       , "shutdown"
                            );
    }
1256695
protected final void requestCheckpoint(boolean persistent)
                    throws ObjectManagerException
    {
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this,
                        cclass,
                        "requestCheckpoint",
                        new Object[] { new Boolean(persistent) });

        // During restart checkpointHelper is not running so don't request a checkpoint.
        // A checkpoint is forced at startup once it is safe to do so.
        if (checkpointHelper != null)
            checkpointHelper.requestCheckpoint(persistent);

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this,
                       cclass,
                       "requestCheckpoint");
    }
787124
protected void close()
                    throws ObjectManagerException
    {
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this, cclass
                        , "close"
                            );

        if (flushHelper != null)
            flushHelper.shutdown(); // Complete outstanding work.
        if (notifyHelper != null)
            notifyHelper.shutdown(); // No longer need a notify thread.

        logFile = null;

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this, cclass
                       , "close"
                            );
    }
264790
public synchronized void flush()
                    throws ObjectManagerException
    {
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled()) {
            trace.entry(this,
                        cclass,
                        "flush");
            trace.exit(this,
                       cclass,
                       "flush");
        }
    }
1369867
@Override
    public void init(RestoreManagerConfig config, SnapshotJobManager jobManager) {
        this.config = config;
        this.jobManager = jobManager;
    }
467112
protected void backout(boolean reUse,
                           Transaction transaction)
                    throws ObjectManagerException {
        final String methodName = "backout";
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this, cclass, methodName, new Object[] { new Boolean(reUse),
                                                                transaction });

        boolean persistentWorkDone = false;
        ManagedObject[] lockedManagedObjects;
        int numberOfLockedManagedObjects = 0;

        synchronized (this) {
            // To defend against two application threads completing the same transaction and trying to
            // continue with it at the same time we check that the Transaction still refers to this one,
            // now that we are synchronized on the InternalTransaction.
            if (transaction.internalTransaction != this) {
                if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                    trace.exit(this, cclass,
                               methodName,
                               new Object[] { "via InvalidTransactionException", transaction.internalTransaction }
                                    );
                // Same behaviour as if the transaction was completed and replaced by
                // objectManagerState.dummyInternalTransaction.
                throw new InvalidStateException(this,
                                                InternalTransaction.stateTerminated,
                                                InternalTransaction.stateNames[InternalTransaction.stateTerminated]);

            } // if (transaction.internalTransaction != this).

            // Only call prePrepare if we have not already prepared the transaction.
            if (state == stateInactive
                || state == stateActiveNonPersistent
                || state == stateActivePersistent) {
                prePrepare(transaction);
            } // If already prepared.

            testState(nextStateForStartBackout);
            setState(nextStateForStartBackout);

            preBackout(transaction); // Tell ManagedObjects the outcome.

            // Is there any logging to do?
            if (state == stateBackingOutPersistent) {
                persistentWorkDone = true;

                TransactionBackoutLogRecord transactionBackoutLogRecord = new TransactionBackoutLogRecord(this);
                objectManagerState.logOutput.writeNext(transactionBackoutLogRecord,
                                                       -logSpaceReserved,
                                                       true,
                                                       true);
                logSpaceReserved = 0;
            } // If logging work to do.

            // Drive the backout method for the included objects.
            // The synchronized block prevents us from taking a checkpoint until all of the
            // ManagedObjects have had their opportunity to update the ObjectStore. If a
            // checkpoint is currently active we will update the current checkpoint set in
            // the ObjectStore, if not we will update the next set of updates.
            lockedManagedObjects = new ManagedObject[includedManagedObjects.size()];

            boolean requiresCurrentPersistentCheckpoint = requiresPersistentCheckpoint
                                                          || (objectManagerState.checkpointStarting == ObjectManagerState.CHECKPOINT_STARTING_PERSISTENT);

            for (java.util.Iterator managedObjectIterator = includedManagedObjects.values().iterator(); managedObjectIterator.hasNext();) {
                ManagedObject managedObject = (ManagedObject) managedObjectIterator.next();
                long managedObjectSequenceNumber = ((Long) managedObjectSequenceNumbers.get(managedObject.owningToken)).longValue();

                if (managedObject.lockedBy(transaction)) {
                    managedObject.backout(transaction,
                                          managedObjectSequenceNumber,
                                          requiresCurrentPersistentCheckpoint);
                    lockedManagedObjects[numberOfLockedManagedObjects++] = managedObject;
                } else {
                    ObjectManagerByteArrayOutputStream serializedBytes = (ObjectManagerByteArrayOutputStream) loggedSerializedBytes.get(managedObject.owningToken);
                    managedObject.optimisticReplaceBackout(transaction,
                                                           serializedBytes,
                                                           managedObjectSequenceNumber,
                                                           requiresCurrentPersistentCheckpoint);
                } // if(managedObject.lockedBy(transaction)).

            } // for... includedManagedObjects.

            setState(nextStateForBackout);
            transactionLock.unLock(objectManagerState);
            postBackout(transaction); // Tell ManagedObjects the outcome is complete.
            // Tidy up the transaction.
            complete(reUse,
                     transaction);
        } // synchronized (this).

        // We don't want to clear the transaction lock held by the managedObject otherwise
        // ManagedObject.wasLocked() will not be able to give the past locked state. The
        // Unlock point wa noted above so now notify the ManagedObject and give a new
        // waiter a chance to acquire the lock. If a new transaction acquires the lock then
        // ManagedObject.wasLocked will return its result for the new transaction and
        // wasLocked() will then be true for an even later time.  Do this after we have release the
        // synchronize lock on InternalTransaction so that we avoid deadlock with ManagedObjects
        // that invoke synchronized InternalTransaction methods.
        for (int i = 0; i < numberOfLockedManagedObjects; i++) {
            synchronized (lockedManagedObjects[i]) {
                lockedManagedObjects[i].notify();
            } // synchronized (lockedManagedObjects[i]).
        } // for... lockedManagedObjects.

        // Tell the ObjectManager that we are done, once the transaction is unlocked
        // in case it is needed for checkpoint.
        objectManagerState.transactionCompleted(this,
                                                persistentWorkDone);
        // See if we need to delay while a checkpoint completes. Applications amy ask to reUSe
        // the same transaction, if so we introduce the delay here. Internal transactions are never
        // reUsed so we don't need to wory about blocking them. This call must be made when we
        // are not synchronized on the transaction because it might block waiting for a checkpoint
        // to complete if the log is full.
        if (reUse)
            objectManagerState.transactionPacing();

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this, cclass, methodName);
    }
353549
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 Object[] { new Byte(version) });
            super.readObject(dataInputStream,
                             objectManagerState);
            if (dataInputStream.readByte() == 1) {
                // The first element in the list.
                head = Token.restore(dataInputStream,
                                     objectManagerState);
                //      The final element in the list.
                tail = Token.restore(dataInputStream,
                                     objectManagerState);
            } // if (dataInputStream.readByte() == 1).
            size = dataInputStream.readLong();
        } catch (java.io.IOException exception) {
            // No FFDC Code Needed.
            ObjectManager.ffdc.processException(this,
                                                cclass,
                                                methodName,
                                                exception,
                                                "1:1620:1.40");

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

        // We cannot set the available head during recovery because the links may get deleted before
        // recovery is complete, instead force a scan when we use availableHead for the first time.
        availableHead = null;
        availableSize = size; // All links are initially available.

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this,
                       cclass,
                       methodName);
    }
761610
public synchronized void preDelete(Transaction transaction)
                    throws ObjectManagerException
    {
        final String methodName = "preDelete";
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this, cclass, methodName, new Object[] { transaction });

        // TODO Remove this fix, we should not need it now we do not split checkpoint sets.
        // Defect 326031
        // We only need to do this check once so at recovery time we
        // can rely on it having been done when the transaction first 
        // ran.
        // TODO: Can we avoid this check by grouping transaction work into a single checkpoint?
        // TODO: Re tested this on 18/6/07 and the failure still occurs even though we now write
        // TODO: complete transactions in a checkpoint. Here is a scenarion that might cause this,
        // TODO: however the actual test ( performance) does the delete for the entry and list as two
        //       separate serial tracactions!
        // 
        //   Application Thread          Checkpoint Helper      LogRecords   
        //  
        //   Delete Entry                                       Delete Entry 
        //   Delete List                                        Delete List
        //                               SetRequiresCheckpoint
        // 
        //                               Checkpoint Start       Checkpoint Start. 
        //                                                      Checkpoint Entry(Deleted)
        //                                                      Checkpoint List(Deleted)
        //
        //   Commit                                             Commit
        //   Delete Entry/List from Store
        //                               Flush ObjectStore             
        //                               Checkpoint End         Checkpoint End.  
        // 
        //   
        //   Crash 
        // 
        //   Recover List in Deleted state, 
        //   Entry not yet recovered in deleted state.

        if (transaction.getObjectManagerStateState() != ObjectManagerState.stateReplayingLog) {
            // The list must be empty, apart from links this transaction will delete.
            Token nextToken = head;
            while (nextToken != null) {
                Link nextLink = (Link) nextToken.getManagedObject();
                if (nextLink.willBeDeleted(transaction))
                    nextToken = nextLink.next;
                else {
                    if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                        trace.exit(this, cclass,
                                   methodName,
                                   "via CollentionNotEmptyException"
                                                   + "size=" + size + "(long)"
                                                   + " nextLink.state=" + nextLink.state + "(int) " + Link.stateNames[nextLink.state]
                                                   + "\n nextLink.getTransactionLock()=" + nextLink.getTransactionLock() + "(transactionLock)"
                                        );

                    throw new CollectionNotEmptyException(this, size, transaction);
                    //System.out.println("LinkedList.preDelete nextLink.state ="+nextLink.state+" "+Link.stateNames[nextLink.state]
                    //                  +"\n nextLink.getTransactionLock()="+nextLink.getTransactionLock() 
                    //                  );
                    //break;
                } // if (  nextLink.state == Link.stateToBeDeleted...
            } // while (nextToken != null).
        } // if not recovering...

        super.preDelete(transaction); // Also takes a lock.
        // Visibility is now restricted to our transaction only.

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this, cclass, methodName);
    }
1078441
public void performRecovery(ObjectManagerState objectManagerState)
                    throws ObjectManagerException {
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this,
                        cclass,
                        "performRecovery",
                        new Object[] { objectManagerState, logicalUnitOfWork, new Integer(transactionState)
                                      , tokensToOptimisticReplace, serializedManagedObjectBytes, tokensToDelete, tokensToNotify }
                            );

        // Replace the objects using their original transaction.
        Transaction transactionForRecovery = objectManagerState.getTransaction(logicalUnitOfWork);

        java.util.Iterator serializedObjectIterator = serializedManagedObjectBytes.iterator();

        // A list of ManagedObjects to add, this lists forces the ManagedObjects to
        // remain in storage while we give them to the Transaction.
        java.util.List managedObjectsToAdd = new java.util.ArrayList(tokensToAdd.size());
        for (java.util.Iterator tokenIterator = tokensToAdd.iterator(); tokenIterator.hasNext();) {
            Token token = (Token) tokenIterator.next();

            // Recover the ManagedObject from the serialized bytes.
            byte managedObjectBytes[] = (byte[]) serializedObjectIterator.next();
            ManagedObject managedObject = ManagedObject.restoreFromSerializedBytes(managedObjectBytes,
                                                                                   objectManagerState);

            ManagedObject managedObjectToAdd = token.setManagedObject(managedObject);
            managedObjectToAdd.state = ManagedObject.stateConstructed;
            managedObjectsToAdd.add(managedObjectToAdd);
        } // for ...tokensToAdd.

        // A list of ManagedObjects to optimistic replace, this lists forces the ManagedObjects to
        // remain in storage while we give them to the Transaction.
        java.util.List managedObjectsToOptimisticReplace = new java.util.ArrayList(tokensToOptimisticReplace.size());

        for (java.util.Iterator tokenIterator = tokensToOptimisticReplace.iterator(); tokenIterator.hasNext();) {
            Token token = (Token) tokenIterator.next();

            // Recover the ManagedObject from the serialized bytes.
            byte managedObjectBytes[] = (byte[]) serializedObjectIterator.next();
            ManagedObject managedObject = ManagedObject.restoreFromSerializedBytes(managedObjectBytes,
                                                                                   objectManagerState);

            ManagedObject managedObjectToReplace = token.setManagedObject(managedObject);
            managedObjectsToOptimisticReplace.add(managedObjectToReplace);
        } // for ...tokensToOptimisticReplace.

        // A list of ManagedObjects to delete, this lists forces the ManagedObjects to
        // remain in storage while we give them to the Transaction.
        java.util.List managedObjectsToDelete = new java.util.ArrayList(tokensToDelete.size());
        // Check that the tokensToDelete all have an underlying managedObject because they may have been deleted
        // from the ObjectStore already.

        for (java.util.Iterator tokenIterator = tokensToDelete.iterator(); tokenIterator.hasNext();) {
            Token token = (Token) tokenIterator.next();

            ManagedObject existingManagedObject = token.getManagedObject();
            if (existingManagedObject == null) {
                // The object may have already been deleted from the ObjectStore,
                // so create a dummy object to keep the transaction happy.
                // The Token will have the ObjecStore and storedObjectIdentifier so the the correct delete in the
                // ObjectStore can take place.
                DummyManagedObject dummyManagedObject = new DummyManagedObject("Created by TransactionOptimisticReplaceLogRecord.performRecovery() (Delete)");
                existingManagedObject = token.setManagedObject(dummyManagedObject);
                existingManagedObject.state = ManagedObject.stateReady;
            } // if(existingManagedObject == null).
            managedObjectsToDelete.add(existingManagedObject);
        } // for tokensToDelete...

        // Check that the tokensToNotify all have an underlying managedObject because they may have been deleted
        // by a subsequent transaction. If we create any dummy objects we must hold a strong reference to them
        // until after the transactionForRecovery.optimisticReplace method has run, otherwise the garbage
        // collector might remove them from the weak reference in Token, and it wont be in. the ObjectStore.
        java.util.List dummyManagedObjectsToNotify = new java.util.ArrayList();

        for (java.util.Iterator tokenIterator = tokensToNotify.iterator(); tokenIterator.hasNext();) {
            Token token = (Token) tokenIterator.next();

            ManagedObject existingManagedObject = token.getManagedObject();
            if (existingManagedObject == null) {
                // The object may have already been deleted from the ObjectStore,
                // so create a dummy object to keep the transaction happy.
                // The Token will have the ObjecStore and storedObjectIdentifier so the the correct delete in the
                // ObjectStore can take place.
                DummyManagedObject dummyManagedObject = new DummyManagedObject("Created by TransactionOptimisticReplaceLogRecord.performRecovery() (Notify)");
                dummyManagedObject.state = ManagedObject.stateReady;
                dummyManagedObjectsToNotify.add(dummyManagedObject);
                token.setManagedObject(dummyManagedObject);
            } // if(existingManagedObject == null).
        } // for tokensToNotify...

        transactionForRecovery.optimisticReplace(managedObjectsToAdd,
                                                 managedObjectsToOptimisticReplace,
                                                 managedObjectsToDelete,
                                                 tokensToNotify);
        transactionForRecovery.internalTransaction.resetState(transactionState);

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this,
                       cclass,
                       "performRecovery");
    }
138547
public synchronized void open(ObjectManagerState objectManagerState)
                    throws ObjectManagerException
    {
        final String methodName = "open";
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this,
                        cclass,
                        methodName,
                        new Object[] { objectManagerState, new Integer(storeStrategy), strategyNames[storeStrategy], storeName });

        this.objectManagerState = objectManagerState;
        // All ManagedObjects are new, sequence number zero through initialSequenceNumbers are reserved.
        sequenceNumber = initialSequenceNumber;
        sequenceNumberLock = new SequenceNumberLock();
        allocationAllowed = true;

        // Tokens can drop out of memory, once they are unreferenced.
        // Other classes need to hold ManagedObjects in memory as long as they need their transient state,
        // for example Transactions hold included ManagedObjects in memory via a strong 
        // reference from a HashTable.
        // This can be a weakValueHashMap because MemoryObjectStore holds a reference to all of its managed
        // objects which in turn hold a reference to their owningToken.
        inMemoryTokens = new WeakValueConcurrentHashMap(concurrency);

        // Set switches depending on the flush strategy.
        switch (storeStrategy) {
            case (STRATEGY_KEEP_ALWAYS):
                persistent = true;
                containsRestartData = true;
                usesSerializedForm = true;
                break;

            case (STRATEGY_KEEP_UNTIL_NEXT_OPEN):
                persistent = false;
                containsRestartData = false;
                usesSerializedForm = true;
                break;

            case (STRATEGY_SAVE_ONLY_ON_SHUTDOWN):
                persistent = false;
                containsRestartData = true;
                usesSerializedForm = false;
                break;

            default:
                if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                    trace.exit(this, cclass, methodName, new Integer(storeStrategy));
                throw new InvalidStoreStrategyException(this, storeStrategy);
        } // switch (storeStrategy).

        objectManagerState.notifyCallbacks(ObjectManagerEventCallback.objectStoreOpened,
                                           new Object[] { this });

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this,
                       cclass,
                       methodName,
                       new Object[] { new Boolean(persistent), new Boolean(containsRestartData), new Boolean(usesSerializedForm) });
    }
687127
public void setState(final int state) throws RepositoryException
   {
      // Need privileges to manage repository.
      SecurityManager security = System.getSecurityManager();
      if (security != null)
      {
         security.checkPermission(JCRRuntimePermissions.MANAGE_REPOSITORY_PERMISSION);
      }

      try
      {
         SecurityHelper.doPrivilegedExceptionAction(new PrivilegedExceptionAction<Void>()
         {
            public Void run() throws RepositoryException
            {
               switch (state)
               {
                  case ManageableRepository.ONLINE :
                     resume();
                     break;
                  case ManageableRepository.OFFLINE :
                     suspend();
                     break;
                  case ManageableRepository.SUSPENDED :
                     suspend();
                     break;
                  default :
                     return null;
               }
               return null;
            }
         });
      }
      catch (PrivilegedActionException e)
      {
         Throwable cause = e.getCause();
         if (cause instanceof RepositoryException)
         {
            throw new RepositoryException(cause);
         }
         else
         {
            throw new RuntimeException(cause);
         }
      }
   }
278770
final void write(ManagedObject managedObject)
                    throws ObjectManagerException
    {
        final String methodName = "write";
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this, cclass, methodName, new Object[] { managedObject });

        ObjectManagerByteArrayOutputStream byteArrayOutputStream = null;
        byte[] serializedBytes = null;
        int serializedBytesLength = 0;
        if (usesSerializedForm) {
            // Pick up and write the latest serialized bytes.

            // It is possible that several threads requested a write one after the
            // other each getting the request added to a different managedObjetsToWrite table,
            // however the first of these through here will clear serializedBytes.
            // It is also possible that the transaction state of the managed object
            // was restored from a checkpoint, in which case the serialized object
            // may already be in the ObjectStore, and the serializedBytes will again be null.

            // Is the Object deleted? It may have got deleted after we release the
            // synchronize lock when we captured the tokensToWrite hashtable but before we
            // actually try to write it. We dont strictly need the test for stateDeleted
            // since once in this state the byteArrayOutputStream will be null.
            if (managedObject.state != ManagedObject.stateDeleted)
                byteArrayOutputStream = managedObject.freeLatestSerializedBytes();

        } else {
            // Not logged so use the current serialized bytes, as long as its not part of a transaction.
            // If it is part of a transaction then the transaction will hold the ManagedObject in memory.
            // Not locked because this is only used by SAVE_ONLY_ON_SHUTDOWN stores at shutdown
            // when no appliaction threads are active.
            if (managedObject.state == ManagedObject.stateReady)
                byteArrayOutputStream = managedObject.getSerializedBytes();
            // The byteArrayOutputStream will have getRleaseSize() == 0;
        } // if ( usesSerializedForm ).

        if (byteArrayOutputStream != null) {
            serializedBytes = byteArrayOutputStream.getBuffer();
            serializedBytesLength = byteArrayOutputStream.getCount();
            // For debugging add guardBytes before and after the serialized
            // ManagedObject.
            if (useGuardBytes) {
                guardByte++;
                byte[] guardedBytes = new byte[guardBytesLength + serializedBytesLength + guardBytesLength];
                java.util.Arrays.fill(guardedBytes // Target
                                      , 0 // From index.
                                      , guardBytesLength - 1 // To index.
                                      , guardByte //Fill byte.
                );
                System.arraycopy(serializedBytes // Source.
                                 , 0 // Source position.
                                 , guardedBytes // Destination.
                                 , guardBytesLength // Destination position.
                                 , serializedBytesLength// Length.
                );
                java.util.Arrays.fill(guardedBytes,
                                      guardBytesLength + serializedBytesLength,
                                      guardBytesLength + serializedBytesLength + guardBytesLength - 1,
                                      guardByte);
                serializedBytes = guardedBytes;
                serializedBytesLength = guardedBytes.length;
            } // if (useGuardBytes).

            //TODO Consider Rounding to a 4K boundary.
            //!! int lengthRequired = ((serializedBytes.length/4096)+1)*4096;

            // Allocate some space for the ManagedObject, if we are recovering, we can reuse already 
            // allocated space and avoid the need to have extra space available in the store. This is 
            // important if we were to crash after flushing the store but before we write checkpoint 
            // end. It that event we would try and write the objects to the store for a second time
            // during recovery and require that it had enough spare space to do this. 
            Directory.StoreArea storeArea;
            boolean addToDirectory = false;
            if (objectManagerState.getObjectManagerStateState() == ObjectManagerState.stateReplayingLog) {
                storeArea = (Directory.StoreArea) directory.getEntry(new Long(managedObject.owningToken.storedObjectIdentifier));
                if (storeArea == null
                    || storeArea.length < serializedBytesLength
                    || storeArea.length + minimumFreeSpaceEntrySize > serializedBytesLength) {
                    FreeSpace freeSpace = allocateSpace(serializedBytesLength);
                    storeArea = (Directory.StoreArea) directory.makeStoreArea(managedObject.owningToken.storedObjectIdentifier,
                                                                              freeSpace.address,
                                                                              freeSpace.length);
                    addToDirectory = true;
                }

            } else {
                FreeSpace freeSpace = allocateSpace(serializedBytesLength);
                storeArea = (Directory.StoreArea) directory.makeStoreArea(managedObject.owningToken.storedObjectIdentifier,
                                                                          freeSpace.address,
                                                                          freeSpace.length);
                addToDirectory = true;
            } // if (objectManagerState.

            if (gatherStatistics)
                numberOfManagedObjectsWritten++;
            writeBuffer(serializedBytes,
                        0,
                        serializedBytesLength,
                        storeArea.byteAddress);

            if (addToDirectory) {
                // We assume that even though the buffer has not been forced to disk, the file system will
                // allow a read of the disk to look into the buffer, hence we go ahead and
                // update the live directory.
                Directory.StoreArea existingStoreArea = (Directory.StoreArea) directory.putEntry(storeArea);

                // If this is a replacement we will eventually recover the space the previous object occupies.
                // Note the free space for now but don't release it until the new Object
                // has been forced to disk.
                if (existingStoreArea != null) {
                    newFreeSpace.add(existingStoreArea);
                } // if (existingStoreArea == null).
            } // if (addToDirectory).

            // Keep count of the space we will eventually release now that we have allocated the space.
            checkpointReleaseSize = checkpointReleaseSize + byteArrayOutputStream.getReleaseSize();
            objectManagerState.returnByteArrayOutputStreamToPool(byteArrayOutputStream);
        } // if (byteArrayOutputStream != null ).

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this, cclass, methodName);
    }
194596
public void print(java.io.PrintWriter printWriter)
    {
        printWriter.println("ObjectManager"
                            + "(String)");
        printWriter.println();
        objectManagerState.logOutput.print(printWriter);
    }