/**
   * Added to flush a particular page of the buffer pool to disk
   *
   * @param pageid the page number in the database.
   * @exception HashOperationException if there is a hashtable error.
   * @exception PageUnpinnedException if there is a page that is already unpinned.
   * @exception PagePinnedException if a page is left pinned.
   * @exception PageNotFoundException if a page is not found.
   * @exception BufMgrException other error occured in bufmgr layer
   * @exception IOException if there is other kinds of I/O error.
   */
  public void flushPage(PageId pageId)
      throws HashOperationException, PageUnpinnedException, PagePinnedException,
          PageNotFoundException, BufMgrException, IOException {

    BufMgrFrameDesc frame = pageTable.get(pageId);

    if (frame != null) {
      if (frame.isDirty()) {
        try {
          SystemDefs.JavabaseDB.write_page(pageId, new Page(frame.getData()));
        } catch (Exception e) {
          throw new BufMgrException(e, "BufrMgr::flushPage: page cant be freed by diskmanager");
        }
      }

      frame.setDirtybit(false);

      if (frame.getPinCount() > 0) {
        throw new PagePinnedException(null, "BufrMgr::flushPage: page is still pinned");
      }

    } else {
      throw new PageNotFoundException(null, "BufrMgr::flushPage: page to be flushed not loaded");
    }
  }
  /**
   * To unpin a page specified by a pageId. If pincount>0, decrement it and if it becomes zero, put
   * it in a group of replacement candidates. if pincount=0 before this call, return error.
   *
   * @param globalPageId_in_a_DB page number in the minibase.
   * @param dirty the dirty bit of the frame
   * @exception ReplacerException if there is a replacer error.
   * @exception PageUnpinnedException if there is a page that is already unpinned.
   * @exception InvalidFrameNumberException if there is an invalid frame number .
   * @exception HashEntryNotFoundException if there is no entry of page in the hash table.
   */
  public void unpinPage(PageId pageId, boolean dirty)
      throws ReplacerException, PageUnpinnedException, HashEntryNotFoundException,
          InvalidFrameNumberException {

    BufMgrFrameDesc frame = pageTable.get(pageId);

    if (frame != null) {
      int pinCount = frame.getPinCount();
      if (pinCount == 0) {
        throw new PageUnpinnedException(
            null, "BufrMgr::unPinPage: page to be unpinned is already unpinned");
      } else {
        frame.unpin();
        if (frame.getPinCount() == 0) replacer.unpin(frame.getFrameNumber());
      }

      frame.setDirtybit(dirty);
    } else {
      throw new HashEntryNotFoundException(
          null, "BufrMgr::unPinPage: page to be unpinned not loaded");
    }
  }