public void freePage(PageId globalPageId) throws 
    InvalidBufferException, 
    ReplacerException, 
    HashOperationException,
    InvalidFrameNumberException,
    PageNotReadException,
    BufferPoolExceededException, 
    PagePinnedException, 
    PageUnpinnedException, 
    HashEntryNotFoundException, 
    BufMgrException,
    DiskMgrException,
    IOException {

    // Current frame descriptor index
    int frameNo = hashTable.lookup(globalPageId); 

    // The current frame descriptor
    FrameDesc frame;
    
    // if globalPageId is not in pool, frameNo < 0 then deallocate 
    if (frameNo < 0) {
      deallocate_page(globalPageId);
      return;
    } // end if
    
    if (frameNo >= numBuffers) {
      throw new InvalidBufferException(null, "BUFMGR: Invalid buffer."); 
    } // end if
    
    frame = frmeTable[frameNo];
      
    try {
      replacer.free(frameNo);
    } catch(Exception e) {
      throw new ReplacerException(e, "BUFMGR: Unable to free from replacer.");
    } // end try
    
    try {
      hashTable.remove(frame.pageNo);
    } catch (Exception e) {
      throw new HashOperationException(e, "BUFMGR, Unable to remove from Page Table");
    } // end try
    
    // Reset frame descriptor
    // NOTE: this should be a FrameDesc method
    frame.pageNo.pid = INVALID_PAGE; 
    frame.dirty = false;
      
    deallocate_page(globalPageId);
      
  } // end freePage()