docs: protected Link insert(Token newToken,
                            Link insertPoint,
                            Transaction transaction)
                      throws ObjectManagerException
      {
          final String methodName = "insert";
          if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
              trace.entry(this, cclass, methodName, new Object[] { newToken,
                                                                  insertPoint,
                                                                  transaction });
  
          // Prevent other transactions using the list until its creation is commited.
          if (!(state == stateReady)
              && !((state == stateAdded) && lockedBy(transaction))) {
  
              if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                  trace.exit(this, cclass, methodName, new Object[] { new Integer(state),
                                                                     stateNames[state] });
              throw new InvalidStateException(this, state, stateNames[state]);
          }
  
          // All replacements to links in the list must be made together, so we
          // construct a single log record for all of them.
          managedObjectsToAdd.clear();
          managedObjectsToReplace.clear();
          reservedSpaceInStore = storeSpaceForAdd();
          owningToken.objectStore.reserve((int) reservedSpaceInStore, false);
  
          // Create the new link and add it to its object store.
          Link newLink = new Link(this,
                                  newToken,
                                  insertPoint.previous,
                                  insertPoint.owningToken,
                                  transaction);
          managedObjectsToAdd.add(newLink);
  
          // Chain the new Link into the list.
          if (insertPoint.previous == null) // Cursor at head of list?
          {
              if (head == null) // Only/first element in the list?
                  tail = newLink.getToken();
              else {
                  insertPoint.previous = newLink.getToken();
                  managedObjectsToReplace.add(insertPoint);
              }
              head = newLink.getToken();
          } else {
              // Chain the new element into the body of the list.
              Link previousLink = (Link) insertPoint.previous.getManagedObject();
              previousLink.next = newLink.getToken();
              managedObjectsToReplace.add(previousLink);
              // Cursor at the end of the list?
              if (insertPoint.owningToken == tail) {
                  tail = newLink.getToken();
              } else { // Not at the end of the list.
                  insertPoint.previous = newLink.getToken();
                  managedObjectsToReplace.add(insertPoint);
              }
          } // If at head of list?
  
          // We dont know where the link is added so assume it is ahead of the
          // availableHead.
          availableHead = head;
          skipToBeDeleted();
  
          incrementSize(); // Adjust list length assuming we will commit.
          managedObjectsToReplace.add(this);
  
          // Harden the updates. If the update fails, because the log is full,
          // we have affected the structure of the list so we will have to 
          // reverse the changes. Reserve enough space to reverse the update if the
          // transaction backs out.
          try {
              transaction.optimisticReplace(managedObjectsToAdd,
                                            managedObjectsToReplace,
                                            null, // No tokens to delete.
                                            null, // No tokens to notify.
                                            +logSpaceForDelete());
              // Give up reserved space, but keep back enough to remove the entry if we have to.
              owningToken.objectStore.reserve((int) (storeSpaceForRemove() - reservedSpaceInStore), false);
  
          } catch (InvalidStateException exception) {
              // No FFDC Code Needed, user error.
              // Remove the link we just added.
              undoAdd(newLink);
  
              if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                  trace.exit(this, cclass, methodName, exception);
              throw exception;
  
          } catch (LogFileFullException exception) {
              // No FFDC Code Needed, InternalTransaction has already done this.
              // Remove the link we just added.
              undoAdd(newLink);
  
              if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                  trace.exit(this, cclass, methodName, exception);
              throw exception;
  
              // We should not see ObjectStoreFullException because we have preReserved 
              // the ObjectStore space.
  //    } catch (ObjectStoreFullException exception) {
  //      // No FFDC Code Needed, InternalTransaction has already done this.
  //      // Remove the link we just added.
  //      undoAdd(newLink);
  // 
  //      if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
  //        trace.exit(this, cclass, methodName, exception);
  //      throw exception;
          } // try.
  
          if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
              trace.exit(this, cclass, methodName, new Object[] { newLink });
          return newLink;
      }