Establish the transient state of this ObjectStore.

@param objectManagerState with which the ObjectStore is registered.
@throws ObjectManagerException
963063
public synchronized void open(ObjectManagerState objectManagerState)
                    throws ObjectManagerException {
        final String methodName = "open";
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this, cclass, methodName, objectManagerState);

        super.open(objectManagerState);

        sharedBuffer = java.nio.ByteBuffer.allocateDirect(1024 * 1024);
        storeChannel = storeFile.getChannel();

        // Make sure no one else can write to the file.
        // Obtain an exclusive lock on the storeFileChannel.
        try {
            storeFileLock = storeChannel.tryLock();
        } catch (java.io.IOException exception) {
            // No FFDC Code Needed.
            ObjectManager.ffdc.processException(this, cclass, "<init>", exception, "1:137:1.39");

            if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                trace.exit(this,
                           cclass,
                           methodName,
                           new Object[] { exception });
            throw new PermanentIOException(this,
                                           exception);
        } // catch (java.io.IOException exception).
        if (storeFileLock == null) { // Did we get the lock?
            if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                trace.exit(this,
                           cclass,
                           methodName,
                           "via StoreFileInUseException, storeName=" + storeName + "(String)");
            throw new StoreFileInUseException(this,
                                              storeName);
        } // (fileLock == null).

        // Now look at the file and initialise the ObjectStore.
        // Read the header, to find the directory and free space map.
        try {
            java.nio.ByteBuffer storeHeader = java.nio.ByteBuffer.allocate(pageSize);
            storeChannel.read(storeHeader);
            storeHeader.flip();

            int versionRead = storeHeader.getInt();

            // Read a known number of signature charaters.
            char[] signatureRead = new char[signature.length()];
            for (int i = 0; i < signature.length(); i++)
                signatureRead[i] = storeHeader.getChar();
            if (!(new String(signatureRead).equals(signature))) {
                if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                    trace.exit(this,
                               cclass,
                               "open"
                               , new Object[] { signatureRead });
                throw new InvalidStoreSignatureException(this,
                                                         new String(signatureRead), signature);
            } // if(!(new String(signatureRead).equals(signature))).

            long objectStoreIdentifierRead = storeHeader.getLong();
            if (Tracing.isAnyTracingEnabled() && trace.isDebugEnabled())
                trace.debug(this,
                            cclass,
                            methodName,
                            new Object[] { new Integer(versionRead),
                                          new String(signatureRead),
                                          new Long(objectStoreIdentifierRead)
                            }
                                );
            // Use the saved value if we are a new store.
            if (objectStoreIdentifier == IDENTIFIER_NOT_SET)
                objectStoreIdentifier = (int) objectStoreIdentifierRead;

            // The byte address of the directory root.
            long directoryRootByteAddress = storeHeader.getLong();
            // The current number of bytes in the directory root.
            long directoryRootLength = storeHeader.getLong();
            // The minimumNodeSize of the directory BTree.
            int directoryMinimumNodeSize = storeHeader.getInt();
            long freeSpaceStoreAreaByteAddress = storeHeader.getLong();
            long freeSpaceStoreAreaLength = storeHeader.getLong();
            // The actual number of free space entries since we have to overestimate the space we need to store them.
            long freeSpaceCount = storeHeader.getLong();

            sequenceNumber = storeHeader.getLong();
            // This is the length we assume we have written.
            storeFileSizeUsed = storeHeader.getLong();
            // Administered limits on store file size.
            minimumStoreFileSize = storeHeader.getLong();
            maximumStoreFileSize = storeHeader.getLong();
            cachedManagedObjectsSize = storeHeader.getInt();

            storeFileSizeAllocated = storeFile.length();

            if (Tracing.isAnyTracingEnabled() && trace.isDebugEnabled())
                trace.debug(this,
                            cclass,
                            methodName,
                            new Object[] { new Long(directoryRootByteAddress)
                                          , new Long(directoryRootLength)
                                          , new Integer(directoryMinimumNodeSize)
                                          , new Long(freeSpaceStoreAreaByteAddress)
                                          , new Long(freeSpaceStoreAreaLength)
                                          , new Long(freeSpaceCount)
                                          , new Long(sequenceNumber)
                                          , new Long(storeFileSizeUsed)
                                          , new Long(minimumStoreFileSize)
                                          , new Long(maximumStoreFileSize)
                                          , new Integer(cachedManagedObjectsSize)
                                          , new Long(storeFileSizeAllocated)
                            }
                                );

            // Are we interested in what's already on the disk?
            if (storeStrategy == STRATEGY_KEEP_ALWAYS
                || storeStrategy == STRATEGY_SAVE_ONLY_ON_SHUTDOWN) {
                // Create the array that locks recently used ManagedObjects into memory.
                cachedManagedObjects = new java.lang.ref.SoftReference[cachedManagedObjectsSize];
                directory = new Directory(directoryMinimumNodeSize,
                                          directoryRootByteAddress,
                                          directoryRootLength);
                if (freeSpaceStoreAreaByteAddress != 0)
                    freeSpaceStoreArea = directory.makeStoreArea(freeSpaceIdentifier,
                                                                 freeSpaceStoreAreaByteAddress,
                                                                 freeSpaceStoreAreaLength);
                readFreeSpaceMap(freeSpaceCount);

            } else if (storeStrategy == STRATEGY_KEEP_UNTIL_NEXT_OPEN) {
                if (Runtime.getRuntime().totalMemory() < Integer.MAX_VALUE)
                    reservedSize = new Atomic32BitLong(0);
                else
                    reservedSize = new Atomic64BitLong(0);
                clear();
            } // if (storeStrategy...

        } catch (java.nio.BufferUnderflowException exception) {
            // The file is empty or did not exist.
            // No FFDC Code Needed, this may be first use of a store.
            if (Tracing.isAnyTracingEnabled() && trace.isEventEnabled())
                trace.event(this,
                            cclass,
                            methodName,
                            exception);

            if (objectManagerState.getObjectManagerStateState() == ObjectManagerState.stateReplayingLog) {
                ObjectManager.ffdc.processException(this, cclass, methodName, exception, "1:267:1.39");

                if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                    trace.exit(this, cclass, methodName, new Object[] { "Buffer underflow:270" });
                throw new PermanentNIOException(this,
                                                exception);
            } // if.

            // Set initial values.
            minimumStoreFileSize = 0;
            maximumStoreFileSize = Long.MAX_VALUE;
            cachedManagedObjectsSize = initialCachedManagedObjectsSize;
            cachedManagedObjects = new java.lang.ref.SoftReference[cachedManagedObjectsSize];

            directory = new Directory(initialDirectoryMinimumNodeSize, 0, 0);
            freeSpaceByAddressHead = null;
            freeSpaceByLength = new java.util.TreeSet(new AbstractSingleFileObjectStore.LengthComparator());
            freeSpaceStoreArea = null;

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

            // Allow for two headers to be written at the front of the file.
            storeFileSizeUsed = pageSize * 2;
            storeFileSizeAllocated = storeFileSizeUsed;
            // allocateSpace() is now initialized,

            // Make sure there is a valid header on the disk, in case we fail after this.
            // It is fatal for the ObjectManager to fail after we extend the file system
            // in setAllocationAllowed() without writing a header as the header will contain zeros.
            writeHeader();
            force();

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

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

        directoryReservedSize = directory.spaceRequired();
        if (Runtime.getRuntime().totalMemory() < Integer.MAX_VALUE)
            reservedSize = new Atomic32BitLong(0);
        else
            reservedSize = new Atomic64BitLong(0);

        // Assume we have already reserved enough space to completely rewrite the directory so any number of
        // node splits or deletions are already accounted for. We now need to say how much space is needed
        // each time an object is added or replaced in the store. This will include enough space to also 
        // complete its removal.
        addSpaceOverhead = 4 + 1 // Space for a new Node, numberOfKeys + flagIsLeaf/flagIsNotLeaf.
                           + 5 * 8 // Space for a new Entry, Identifier,address,length,childAddress,childLength.
                           + 2 * 8 // An entry in the free space map for the node when it is rewritten.
                           + 2 * 8; // An entry in the free space map when the ManagedObject is removed.  
        // For debugging add guardBytes before and after the Node metadata and  before and after the payload.
        if (useGuardBytes)
            addSpaceOverhead = addSpaceOverhead + 2 * 2 * guardBytesLength;

        setAllocationAllowed();

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this,
                       cclass,
                       methodName);
    }
661735
public final void shutdown()
                    throws ObjectManagerException
    {
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this, cclass
                        , "shutdown"
                            );

        objectManagerState.shutdown();

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this, cclass
                       , "shutdown"
                            );
    }
1361586
public void store(Object obj) throws PersistenceBrokerException
    {
        obj = extractObjectToStore(obj);
        // only do something if obj != null
        if(obj == null) return;

        ClassDescriptor cld = getClassDescriptor(obj.getClass());
        /*
        if one of the PK fields was null, we assume the objects
        was new and needs insert
        */
        boolean insert = serviceBrokerHelper().hasNullPKField(cld, obj);
        Identity oid = serviceIdentity().buildIdentity(cld, obj);
        /*
        if PK values are set, lookup cache or db to see whether object
        needs insert or update
        */
        if (!insert)
        {
            insert = objectCache.lookup(oid) == null
                && !serviceBrokerHelper().doesExist(cld, oid, obj);
        }
        store(obj, oid, cld, insert);
    }
355229
private void write(ManagedObject managedObject)
                    throws ObjectManagerException
    {
        final String methodName = "write";
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this,
                        cclass,
                        methodName,
                        new Object[] { managedObject });

        // Pick up and write the latest serialized bytes.
        ObjectManagerByteArrayOutputStream serializedBytes = null;
        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.
            if (managedObject.state != ManagedObject.stateDeleted)
                serializedBytes = 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)
                serializedBytes = managedObject.getSerializedBytes();
        } // if ( usesSerializedForm ).

        // It is possible that several threads requested a write one after the other each getting the request added
        // to a different tokensToWrite table, however the first of these through here will clear serializedBytes.
        if (serializedBytes != null) { // Already done by another thread?
            try {
                java.io.FileOutputStream storeFileOutputStream = new java.io.FileOutputStream(storeDirectoryName
                                                                                              + java.io.File.separator
                                                                                              + managedObject.owningToken.storedObjectIdentifier);
                storeFileOutputStream.write(serializedBytes.getBuffer(), 0, serializedBytes.getCount());
                storeFileOutputStream.flush();
                storeFileOutputStream.close();

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

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

            managedObjectsOnDisk.add(new Long(managedObject.owningToken.storedObjectIdentifier));
        } // if (serializedBytes != null ).

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this,
                       cclass,
                       methodName);
    }
831703
public function injectObjectManager(ObjectManagerInterface $objectManager): void
    {
        if ($this->objectManager === null) {
            $this->objectManager = $objectManager;
            /** @var CacheManager $cacheManager */
            $cacheManager = $this->objectManager->get(CacheManager::class);
            $this->runtimeExpressionsCache = $cacheManager->getCache('Flow_Aop_RuntimeExpressions');
        }
    }
12885
public synchronized void close()
                    throws ObjectManagerException {
        final String methodName = "close";
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this, cclass, methodName);

        super.close();

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this, cclass, methodName);
    }
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"
                            );
    }
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);
    }
1019767
@Override
    protected <T> void bind(LifecycleManager manager, Class<T> clazz, T object) throws ObjectAlreadyAssociatedException {
        // update binding
        STORE.putIfAbsent(clazz, new Binding());
        Binding binding = STORE.get(clazz);

        if (binding.put(object, manager) != null) {
            throw new ObjectAlreadyAssociatedException();
        }

        // update tracking
        TRACK.putIfAbsent(manager, new Tracking());
        Tracking tracking = TRACK.get(manager);

        tracking.add(clazz);
    }
716005
private final synchronized void unlock()
                    throws ObjectManagerException
    {
        final String methodName = "unlock";
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this,
                        cclass,
                        methodName,
                        new Object[] { transactionLock });

        setState(nextStateForUnlock); // Make the state change. 

        transactionLock = new TransactionLock(null);
        numberOfLocksTaken = 0;
        notify(); // Wake up one waiter.

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this,
                       cclass,
                       methodName);
    }
306258
public void setState(TransferState state) {
        synchronized (this) {
            this.state = state;
        }
        for ( TransferStateChangeListener listener : stateChangeListeners ) {
            listener.transferStateChanged(this, state);
        }
    }
744444
private void setState(final RunnableProcessState newState) {
    if (!this.state.isLegal(newState)) {
      throw new IllegalStateException("Transition from " + this.state + " to " + newState + " is illegal");
    }
    this.state = newState;
  }
1183827
public final void setName(String newName)
                    throws ObjectManagerException {
        final String methodName = "setName";
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this, cclass, methodName, new Object[] { newName, storeName });

        objectManagerState.renameObjectStore(this, newName);

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this, cclass, methodName);
    }
380333
public void performRecovery(ObjectManagerState objectManagerState)
                    throws ObjectManagerException {
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this,
                        cclass,
                        "performRecovery",
                        objectManagerState);

        if (Tracing.isAnyTracingEnabled() && trace.isDebugEnabled())
            trace.debug(this,
                        cclass,
                        "logicalUnitOfWork=" + logicalUnitOfWork + "(LogicalUnitOfWork)"
                                        + "\n transactionState=" + transactionState + "(int)"
                                        + "\n tokensToAdd=" + tokensToAdd + "(java.util.Collection)"
                                        + "\n tokensToReplace=" + tokensToReplace + "(java.util.Collecton)"
                                        + "\n serializedBytesToReplace=" + serializedBytesToReplace + "(java.util.Collection)"
                                        + "\n tokensToOptimisticReplace=" + tokensToOptimisticReplace + "(java.util.Collection)"
                                        + "\n tokensToDelete=" + tokensToDelete + "(java.util.Collection)"
                                        + "\n tokensToNotify=" + tokensToNotify + "(java.util.Collection)");

        // In principle we should test to see if objectManagerState.checkpointEndSee is true, 
        // because if it is we dont need to do this processing because the transaction is 
        // already in its correct state, however there is also no harm in processing this again. 
        // We have started an new checkpoint but not completed it.

        // Redo the operations of the ManagedObject using its original Transaction.
        Transaction transactionForRecovery = objectManagerState.getTransaction(logicalUnitOfWork);

        // Recover the Added ManagedObjects.
        for (java.util.Iterator tokenIterator = tokensToAdd.iterator(); tokenIterator.hasNext();) {
            Token token = (Token) tokenIterator.next();
            ManagedObject existingManagedObject = token.getManagedObject();
            // If a subsequent transaction has deleted the ManagedObject we dont need to recover it.
            if (existingManagedObject != null) {
                // Revert to constructed state.
                existingManagedObject.state = ManagedObject.stateConstructed;
                transactionForRecovery.addFromCheckpoint(existingManagedObject);
            } // if(existingManagedObject != null).
        } // for ... tokensToAdd.

        // Recover the Replace ManagedObjects.
        java.util.Iterator serializedBytesIterator = serializedBytesToReplace.iterator();
        for (java.util.Iterator tokenIterator = tokensToReplace.iterator(); tokenIterator.hasNext();) {
            Token token = (Token) tokenIterator.next();
            ManagedObject existingManagedObject = token.getManagedObject();
            byte[] managedObjectBytes = (byte[]) serializedBytesIterator.next();
            ManagedObject replacementManagedObject = ManagedObject.restoreFromSerializedBytes(managedObjectBytes,
                                                                                              objectManagerState);
            // If a subsequent transaction has deleted the ManagedObject we dont need to recover it.
            if (existingManagedObject != null) {
                // Replace what we already have with this version.
                transactionForRecovery.lock(existingManagedObject);
                // Make the underlying object the way it was when we made the original transaction.replace()
                // call.
                token.setManagedObject(replacementManagedObject);
                transactionForRecovery.replaceFromCheckpoint(existingManagedObject,
                                                             managedObjectBytes);
            } // if(existingManagedObject != null).
        } // for ... tokensToReplace.

        // Recover the Optimistic Replace ManagedObjects.
        for (java.util.Iterator tokenIterator = tokensToOptimisticReplace.iterator(); tokenIterator.hasNext();) {
            Token token = (Token) tokenIterator.next();
            ManagedObject existingManagedObject = token.getManagedObject();
            // If a subsequent transaction has deleted the ManagedObject we dont need to recover it.
            if (existingManagedObject != null) {
                transactionForRecovery.optimisticReplaceFromCheckpoint(existingManagedObject);
            } // if(existingManagedObject != null).
        } // for ... tokensToOptimisticReplace.

        // Recover the Delete ManagedObjects.
        for (java.util.Iterator tokenIterator = tokensToDelete.iterator(); tokenIterator.hasNext();) {
            Token token = (Token) tokenIterator.next();
            ManagedObject existingManagedObject = token.getManagedObject();
            // If the object has already been deleted we need not do anything.
            if (existingManagedObject != null) {
                transactionForRecovery.deleteFromCheckpoint(existingManagedObject);
            } // if(existingManagedObject != null).
        } // for ... tokensToDelete.

        // Recover the Notify ManagedObjects.
        for (java.util.Iterator tokenIterator = tokensToNotify.iterator(); tokenIterator.hasNext();) {
            Token token = (Token) tokenIterator.next();
            ManagedObject existingManagedObject = token.getManagedObject();
            // If the object has already been deleted we need not do anything.
            if (existingManagedObject != null) {
                transactionForRecovery.notifyFromCheckpoint(token);
            } // if(existingManagedObject != null).
        } // for ... tokensToNotify.

        transactionForRecovery.internalTransaction.resetState(transactionState);

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this,
                       cclass,
                       "performRecovery");
    }
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);
    }
1369867
@Override
    public void init(RestoreManagerConfig config, SnapshotJobManager jobManager) {
        this.config = config;
        this.jobManager = jobManager;
    }
58154
public synchronized void open(ObjectManagerState objectManagerState)
                    throws ObjectManagerException {
        final String methodName = "open";
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this, cclass, methodName, objectManagerState);

        super.open(objectManagerState);

        byteArrayOutputStream = new ObjectManagerByteArrayOutputStream(pageSize);

        // Now look at the file and initialise the ObjectStore.
        // Read the header, to find the directory and free space map.
        try {
            int versionRead = storeFile.readInt();

            // Read a known number of signature charaters.
            char[] signatureRead = new char[signature.length()];
            for (int i = 0; i < signature.length(); i++)
                signatureRead[i] = storeFile.readChar();
            if (!(new String(signatureRead).equals(signature))) {
                if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                    trace.exit(this,
                               cclass,
                               "open"
                               , new Object[] { signatureRead });
                throw new InvalidStoreSignatureException(this,
                                                         new String(signatureRead), signature);
            } // if(!(new String(signatureRead).equals(signature))).

            long objectStoreIdentifierRead = storeFile.readLong();
            if (Tracing.isAnyTracingEnabled() && trace.isDebugEnabled())
                trace.debug(this,
                            cclass,
                            methodName,
                            new Object[] { new Integer(versionRead),
                                          new String(signatureRead),
                                          new Long(objectStoreIdentifierRead)
                            }
                                );
            // Use the saved value if we are a new store.
            if (objectStoreIdentifier == IDENTIFIER_NOT_SET)
                objectStoreIdentifier = (int) objectStoreIdentifierRead;

            // The byte address of the directory root.
            long directoryRootByteAddress = storeFile.readLong();
            // The current number of bytes in the directory root.
            long directoryRootLength = storeFile.readLong();
            // The minimumNodeSize of the directory BTree.
            int directoryMinimumNodeSize = storeFile.readInt();
            long freeSpaceStoreAreaByteAddress = storeFile.readLong();
            long freeSpaceStoreAreaLength = storeFile.readLong();
            // The actual number of free space entries since we have to overestimate the space we need to store them.
            long freeSpaceCount = storeFile.readLong();

            sequenceNumber = storeFile.readLong();
            // This is the length we assume we have written.
            storeFileSizeUsed = storeFile.readLong();
            // Administered limits on store file size.
            minimumStoreFileSize = storeFile.readLong();
            maximumStoreFileSize = storeFile.readLong();
            cachedManagedObjectsSize = storeFile.readInt();

            storeFileSizeAllocated = storeFile.length();

            if (Tracing.isAnyTracingEnabled() && trace.isDebugEnabled())
                trace.debug(this,
                            cclass,
                            methodName,
                            new Object[] { new Long(directoryRootByteAddress)
                                          , new Long(directoryRootLength)
                                          , new Integer(directoryMinimumNodeSize)
                                          , new Long(freeSpaceStoreAreaByteAddress)
                                          , new Long(freeSpaceStoreAreaLength)
                                          , new Long(freeSpaceCount)
                                          , new Long(sequenceNumber)
                                          , new Long(storeFileSizeUsed)
                                          , new Long(minimumStoreFileSize)
                                          , new Long(maximumStoreFileSize)
                                          , new Integer(cachedManagedObjectsSize)
                                          , new Long(storeFileSizeAllocated)
                            }
                                );

            // Are we interested in what's already on the disk?
            if (storeStrategy == STRATEGY_KEEP_ALWAYS
                || storeStrategy == STRATEGY_SAVE_ONLY_ON_SHUTDOWN) {
                // Create the array that locks recently used ManagedObjects into memory.
                cachedManagedObjects = new java.lang.ref.SoftReference[cachedManagedObjectsSize];
                directory = new Directory(directoryMinimumNodeSize,
                                          directoryRootByteAddress,
                                          directoryRootLength);
                if (freeSpaceStoreAreaByteAddress != 0)
                    freeSpaceStoreArea = directory.makeStoreArea(freeSpaceIdentifier,
                                                                 freeSpaceStoreAreaByteAddress,
                                                                 freeSpaceStoreAreaLength);
                readFreeSpaceMap(freeSpaceCount);

            } else if (storeStrategy == STRATEGY_KEEP_UNTIL_NEXT_OPEN) {
                if (Runtime.getRuntime().totalMemory() < Integer.MAX_VALUE)
                    reservedSize = new Atomic32BitLong(0);
                else
                    reservedSize = new Atomic64BitLong(0);
                clear();
            } // if (storeStrategy...

        } catch (java.io.EOFException exception) {
            // The file is empty or did not exist.
            // No FFDC Code Needed, this may be first use of a store.
            if (Tracing.isAnyTracingEnabled() && trace.isEventEnabled())
                trace.event(this,
                            cclass,
                            methodName,
                            exception);

            if (objectManagerState.getObjectManagerStateState() == ObjectManagerState.stateReplayingLog) {
                ObjectManager.ffdc.processException(this, cclass, methodName, exception, "1:241:1.35");

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

            // Set initial values.
            minimumStoreFileSize = 0;
            maximumStoreFileSize = Long.MAX_VALUE;
            cachedManagedObjectsSize = initialCachedManagedObjectsSize;
            cachedManagedObjects = new java.lang.ref.SoftReference[cachedManagedObjectsSize];

            directory = new Directory(initialDirectoryMinimumNodeSize, 0, 0);
            freeSpaceByAddressHead = null;
            freeSpaceByLength = new java.util.TreeSet(new AbstractSingleFileObjectStore.LengthComparator());
            freeSpaceStoreArea = null;

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

            // Allow for two headers to be written at the front of the file.
            storeFileSizeUsed = pageSize * 2;
            storeFileSizeAllocated = storeFileSizeUsed;
            // allocateSpace() is now initialized,

            // Make sure there is a valid header on the disk, in case we fail after this.
            // It is fatal for the ObjectManager to fail after we extend the file system
            // in setAllocationAllowed() without writing a header as the header will contain zeros.
            writeHeader();
            force();

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

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

        directoryReservedSize = directory.spaceRequired();
        if (Runtime.getRuntime().totalMemory() < Integer.MAX_VALUE)
            reservedSize = new Atomic32BitLong(0);
        else
            reservedSize = new Atomic64BitLong(0);

        // Assume we have already reserved enough space to completely rewrite the directory so any number of
        // node splits or deletions are already accounted for. We now need to say how much space is needed
        // each time an object is added or replaced in the store. This will include enough space to also 
        // complete its removal.
        addSpaceOverhead = 4 + 1 // Space for a new Node, numberOfKeys + flagIsLeaf/flagIsNotLeaf.
                           + 5 * 8 // Space for a new Entry, Identifier,address,length,childAddress,childLength.
                           + 2 * 8 // An entry in the free space map for the node when it is rewritten.
                           + 2 * 8; // An entry in the free space map when the ManagedObject is removed.  
        // For debugging add guardBytes before and after the Node metadata and  before and after the payload.
        if (useGuardBytes)
            addSpaceOverhead = addSpaceOverhead + 2 * 2 * guardBytesLength;

        setAllocationAllowed();

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