PhysicalRowId:A physical rowid is nothing else than a pointer to a physical location
 in a file - a (block, offset) tuple.
 里面有方法:
 /** Returns the block number */
    long getBlock() {
        return block.readLong(pos + O_BLOCK);
    }
   
    /** Sets the block number */
    void setBlock(long value) {
        block.writeLong(pos + O_BLOCK, value);
    }
    还不是很明白这个block number和rowid是什么关系,好像这个number的设置是很自由的,奇怪
FreePhysicalRowId:This class extends the physical rowid with a size value to indicated
 the size of a free rowid on the free rowid list.
 这个类就是比PhysicalRowId多了一个size的设置,这个size是a free rowid的,不是很明白这句话,rowid需要这个size干吗?

 FreePhysicalRowId id = ......
 id.setBlock(1);
 id.setOffset((short) 2);
 id.setSize(3);

FreePhysicalRowIdPage:describe a page that holds physical rowids that were freed.
 这个类管理rowid,其主要方法如下:
  
    // slots we returned.
    FreePhysicalRowId[] slots = new FreePhysicalRowId[ELEMS_PER_PAGE];
   
    /** Returns the number of free rowids */
    short getCount() {
  return block.readShort(O_COUNT);
    }

    /** Sets the number of free rowids */
    private void setCount(short i) {
  block.writeShort(O_COUNT, i);
    }

    /** Frees a slot */
    void free(int slot) {
  get(slot).setSize(0);
  setCount((short) (getCount() - 1));
    }

    /** Allocates a slot */
    FreePhysicalRowId alloc(int slot) {
  setCount((short) (getCount() + 1));
  return get(slot);
    }

    /** Returns true if a slot is allocated */
    boolean isAllocated(int slot) {
  return get(slot).getSize() != 0;
    }

    /** Returns true if a slot is free */
    boolean isFree(int slot) {
  return !isAllocated(slot);
    }
   
   
    /** Returns the value of the indicated slot */
    FreePhysicalRowId get(int slot) {
  if (slots[slot] == null)
      slots[slot] = new FreePhysicalRowId(block, slotToOffset(slot));;
  return slots[slot];
    }

    /** Converts slot to offset */
    short slotToOffset(int slot) {
  return (short) (O_FREE +
      (slot * FreePhysicalRowId.SIZE));
    }
   
    /**
     *  Returns first free slot, -1 if no slots are available
     */
    int getFirstFree() {
  for (int i = 0; i < ELEMS_PER_PAGE; i++) {
      if (isFree(i))
    return i;
  }
  return -1;
    }

    /**
     *  Returns first slot with available size >= indicated size, 
     *  or -1 if no slots are available.
     **/
    int getFirstLargerThan(int size) {
  for (int i = 0; i < ELEMS_PER_PAGE; i++) {
      if (isAllocated(i) && get(i).getSize() >= size)
    return i;
  }
  return -1;
    }
   
  以上主要是进行分配和释放工作,最后两个方法用于查找第一个free的slot和根据size查找slot,很有用,要记住。
  在db中,一个库包含多个table,一个table包含多个记录。一个RecordFile应该就是一个db吧。
 
FreePhysicalRowIdPageManager:manages free physical rowid pages and provides methods
 to free and allocate physical rowids on a high level.
它有两个成员变量:
    // our record file
    protected RecordFile _file;

    // our page manager
    protected PageManager _pageman;

RecordFile和PageManager这两个类前面都有研究,应该不是问题。FreePhysicalRowIdPageManager
只有两个方法:

    /**
     *  Returns a free physical rowid of the indicated size, or
     *  null if nothing was found.
     */
    Location get( int size )
   
    /**
     *  Puts the indicated rowid on the free list
     */
    void put(Location rowid, int size)
   
这里的get方法很重要,从这个方法里面可以看出数据文件的组织方式:

    /**
     *  Returns a free physical rowid of the indicated size, or
     *  null if nothing was found.
     */
    Location get( int size )
        throws IOException
    {
        // Loop through the free physical rowid list until we find
        // a rowid that's large enough.
        Location retval = null;
        PageCursor curs = new PageCursor( _pageman, Magic.FREEPHYSIDS_PAGE );

        while (curs.next() != 0) {
            FreePhysicalRowIdPage fp = FreePhysicalRowIdPage
                .getFreePhysicalRowIdPageView( _file.get( curs.getCurrent() ) );
            int slot = fp.getFirstLargerThan( size );
            if ( slot != -1 ) {
                // got one!
                retval = new Location( fp.get( slot ) );

                int slotsize = fp.get( slot ).getSize();
                fp.free( slot );
                if ( fp.getCount() == 0 ) {
                    // page became empty - free it
                    _file.release( curs.getCurrent(), false );
                    _pageman.free( Magic.FREEPHYSIDS_PAGE, curs.getCurrent() );
                } else {
                    _file.release( curs.getCurrent(), true );
                }

                return retval;
            } else {
                // no luck, go to next page
                _file.release( curs.getCurrent(), false );
            }

        }
        return null;
    }
  当保存数据时,先得到FreePhysicalRowIdPage里面去查有没有合适大小的slot可用。得到合适的slot后,就得到了
  FreePhysicalRowId。FreePhysicalRowId持有size信息,这个size前面没有搞清楚,到这里就清楚了,其实是可存放
  数据文件的size。FreePhysicalRowId还持有BlockIo和offset信息,这个被Location使用,get方法最后也是返回Location对象。
 
PhysicalRowIdManager:manages physical row ids, and their data.