docs: public synchronized Token remove(Object key,
                                       Transaction transaction)
                      throws ObjectManagerException {
          final String methodName = "remove";
          if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
              trace.entry(this, cclass, methodName, new Object[] { key,
                                                                  transaction });
  
          Token returnValue = null; // The returned value.
  
          // Find the entry in to be removed. Actual removal from the structure of
          // the tree takes place when we know the outcome of the transaction is 
          // commit. 
          Entry entry = getEntry(key);
  
          // Defect 562227
          // We only need to do more (especially reserve space in the store) 
          // if we have found the supplied key in our map.
          if (entry != null) {
              boolean spaceReserved = false;
  
              // Capture the ObjectManagers unlock sequence number. Anything unlocked after 
              // this will not count. The next line delimits the pont before which additions to 
              // list must committed and unlocked.
              long transactionUnlockPoint = Long.MAX_VALUE; // All transactions end before this.
              if (transaction != null)
                  transactionUnlockPoint = transaction.getTransactionUnlockSequence();
  
              try {
                  // Note the different behaviour compared to LinkedLists. Here we hold the
                  // lock on the tree while the delete log record is written and then mark the Entry to be 
                  // deleted. This means we don't have to worry about the log filling because if it does, we
                  // won't reach this point and the state will not change.
                  synchronized (transaction.internalTransaction) {
                      synchronized (this) {
                          duplicateSearch: while (entry != null) { // Matching entry?
                              if (compare(key, entry.key) != 0)
                                  break duplicateSearch;
  
                              if ((entry.state == Entry.stateToBeAdded)
                                  && entry.lockedBy(transaction)) {
                                  // Log what we intend to do. Reserve enough spare log space so that the eventual 
                                  // optimistic replace that removes the entry from the tree is certain to succeed 
                                  // in being written as well.
                                  transaction.delete(entry, logSpaceForDelete);
                                  returnValue = entry.getValue();
                                  // Mark for deletion. 
                                  entry.requestDelete(transaction);
                                  // In the case where we delete an entry added by the same transaction we have not incremented 
                                  // the available size yet because we have not yet committed so we would not decrement it.
  
                                  break duplicateSearch;
  
                              } else if ((entry.state == Entry.stateAdded)
                                         && !entry.wasLocked(transactionUnlockPoint)) {
                                  // Reserve space in the store, if not available, we fail here.
                                  owningToken.objectStore.reserve((int) storeSpaceForRemove(), false);
                                  spaceReserved = true;
  
                                  transaction.delete(entry, logSpaceForDelete);
                                  returnValue = entry.getValue();
                                  // Mark for deletion.
                                  entry.requestDelete(transaction);
                                  // If the entry was available to all adjust the visible length available.
                                  availableSize--;
  
                                  break duplicateSearch;
  
                              } else { // Put cannot get this one.
                              } // if OK to get.
  
                              entry = (Entry) successor(entry);
                          } // duplicateSearch while (entry != null).
                      } // synchronized (this).
                  } // synchronized (transaction.internalTransaction).
              } catch (LogFileFullException exception) {
                  // No FFDC Code Needed, transaction.delete() has already done this.
                  // Release space we reserved in the store.
                  if (spaceReserved)
                      owningToken.objectStore.reserve(-(int) storeSpaceForRemove(), false);
                  if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                      trace.exit(this, cclass, methodName, exception);
                  throw exception;
  
                  // We should not see ObjectStoreFullException because the ObjectStore already 
                  // holds sufficient space to guarantee deletes work.
                  //    } catch (ObjectStoreFullException exception) {
                  //    // No FFDC Code Needed, transaction.delete() has already done this.
                  //    unRemove();
                  //    if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                  //    trace.exit(this, cclass, methodName, exception);
                  //    throw exception;
  
              } catch (InvalidStateException exception) {
                  // No FFDC Code Needed.
                  ObjectManager.ffdc.processException(this, cclass, methodName, exception, "1:1057:1.44");
                  // Release space we reserved in the store.
                  if (spaceReserved)
                      owningToken.objectStore.reserve(-(int) storeSpaceForRemove(), false);
                  if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                      trace.exit(this, cclass, methodName, exception);
                  throw exception;
              } // catch (LogFileFullException exception).
          }
  
          if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
              trace.exit(this, cclass, methodName, new Object[] { returnValue });
          return returnValue;
      }