code: @Override
  	public void insert(SearchKey key, RecordId dataRecordId, boolean doLogicalLogging) {
  		if (tx.isReadOnly())
  			throw new UnsupportedOperationException();
  
  		// search leaf block for insertion
  		search(new SearchRange(key), SearchPurpose.INSERT);
  		DirEntry newEntry = leaf.insert(dataRecordId);
  		leaf.close();
  		if (newEntry == null)
  			return;
  		
  		// log the logical operation starts
  		if (doLogicalLogging)
  			tx.recoveryMgr().logLogicalStart();
  
  		// insert the directory entry from the lowest directory
  		for (int i = dirsMayBeUpdated.size() - 1; i >= 0; i--) {
  			BlockId dirBlk = dirsMayBeUpdated.get(i);
  			BTreeDir dir = new BTreeDir(dirBlk, keyType, tx);
  			newEntry = dir.insert(newEntry);
  			dir.close();
  			if (newEntry == null)
  				break;
  		}
  		if (newEntry != null) {
  			BTreeDir root = new BTreeDir(rootBlk, keyType, tx);
  			root.makeNewRoot(newEntry);
  			root.close();
  		}
  		dirsMayBeUpdated = null;
  		
  		// log the logical operation ends
  		if (doLogicalLogging)
  			tx.recoveryMgr().logIndexInsertionEnd(ii.indexName(), key,
  					dataRecordId.block().number(), dataRecordId.id());
  	}
docs: Inserts the specified record into the index. The method first traverses
  the directory to find the appropriate leaf page; then it inserts the
  record into the leaf. If the insertion causes the leaf to split, then the
  method calls insert on the root, passing it the directory entry of the
  new leaf page. If the root node splits, then {@link BTreeDir#makeNewRoot}
  is called.
  
  @see Index#insert(SearchKey, RecordId, boolean)