docs: 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);
      }