/**
   * Check and purge committed deleted rows on a page.
   *
   * <p>
   *
   * @return true, if no purging has been done on page, and thus latch can be released before end
   *     transaction. Otherwise the latch on the page can not be released before commit.
   * @param page A non-null, latched page must be passed in. If all rows on page are purged, then
   *     page will be removed and latch released.
   * @exception StandardException Standard exception policy.
   */
  protected final boolean purgeCommittedDeletes(Page page) throws StandardException {
    boolean purgingDone = false;

    // The number records that can be reclaimed is:
    // total recs - recs_not_deleted
    int num_possible_commit_delete = page.recordCount() - page.nonDeletedRecordCount();

    if (num_possible_commit_delete > 0) {
      // loop backward so that purges which affect the slot table
      // don't affect the loop (ie. they only move records we
      // have already looked at).
      for (int slot_no = page.recordCount() - 1; slot_no >= 0; slot_no--) {
        boolean row_is_committed_delete = page.isDeletedAtSlot(slot_no);

        if (row_is_committed_delete) {
          // At this point we only know that the row is
          // deleted, not whether it is committed.

          // see if we can purge the row, by getting an
          // exclusive lock on the row.  If it is marked
          // deleted and we can get this lock, then it
          // must be a committed delete and we can purge
          // it.

          RecordHandle rh =
              page.fetchFromSlot(
                  (RecordHandle) null,
                  slot_no,
                  RowUtil.EMPTY_ROW,
                  RowUtil.EMPTY_ROW_FETCH_DESCRIPTOR,
                  true);

          row_is_committed_delete = this.lockRowAtSlotNoWaitExclusive(rh);

          if (row_is_committed_delete) {
            purgingDone = true;

            page.purgeAtSlot(slot_no, 1, false);
          }
        }
      }
    }
    if (page.recordCount() == 0) {

      // Deallocate the current page with 0 rows on it.
      this.removePage(page);

      // removePage guarantees to unlatch the page even if an
      // exception is thrown. The page is protected against reuse
      // because removePage locks it with a dealloc lock, so it
      // is OK to release the latch even after a purgeAtSlot is
      // called.
      // @see ContainerHandle#removePage

      purgingDone = true;
    }

    return (purgingDone);
  }