Class: Innodb::Xdes

Inherits:
Object
  • Object
show all
Defined in:
lib/innodb/xdes.rb

Overview

An InnoDB “extent descriptor entry” or “XDES”. These structures are used in the XDES entry array contained in FSP_HDR and XDES pages.

Note the distinction between XDES entries and XDES pages.

Constant Summary collapse

BITS_PER_PAGE =

Number of bits per page in the XDES entry bitmap field. Currently XDES entries store two bits per page, with the following meanings:

  • 1 = free (the page is free, or not in use)

  • 2 = clean (currently unused, always 1 when initialized)

2
BITMAP_BV_FREE =

The bit value for a free page.

1
BITMAP_BV_CLEAN =

The bit value for a clean page (currently unused in InnoDB).

2
BITMAP_BV_ALL =

The bitwise-OR of all bitmap bit values.

(BITMAP_BV_FREE | BITMAP_BV_CLEAN)
STATES =

The values used in the :state field indicating what the extent is used for (or what list it is on).

{
  1 => :free,       # The extent is completely empty and unused, and should
                    # be present on the filespace's FREE list.

  2 => :free_frag,  # Some pages of the extent are used individually, and
                    # the extent should be present on the filespace's
                    # FREE_FRAG list.

  3 => :full_frag,  # All pages of the extent are used individually, and
                    # the extent should be present on the filespace's
                    # FULL_FRAG list.

  4 => :fseg,       # The extent is wholly allocated to a file segment.
                    # Additional information about the state of this extent
                    # can be derived from the its presence on particular
                    # file segment lists (FULL, NOT_FULL, or FREE).
}

Instance Method Summary collapse

Constructor Details

#initialize(page, cursor) ⇒ Xdes

Returns a new instance of Xdes.



42
43
44
45
# File 'lib/innodb/xdes.rb', line 42

def initialize(page, cursor)
  @page = page
  @xdes = read_xdes_entry(page, cursor)
end

Instance Method Details

#each_page_statusObject

Iterate through all pages represented by this extent descriptor, yielding a page status hash for each page, containing the following fields:

:page   The page number.
:free   Boolean indicating whether the page is free.
:clean  Boolean indicating whether the page is clean (currently
        this bit is unused by InnoDB, and always set true).


84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/innodb/xdes.rb', line 84

def each_page_status
  unless block_given?
    return enum_for(:each_page_status)
  end

  bitmap = xdes[:bitmap].enum_for(:each_byte)

  bitmap.each_with_index do |byte, byte_index|
    (0..3).each_with_index do |page, page_index|
      page_number = xdes[:start_page] + (byte_index * 4) + page_index
      page_bits = ((byte >> (page * BITS_PER_PAGE)) & BITMAP_BV_ALL)
      page_status = {
        :page   => page_number,
        :free   => (page_bits & BITMAP_BV_FREE  != 0),
        :clean  => (page_bits & BITMAP_BV_CLEAN != 0),
      }
      yield page_status
    end
  end

  nil
end

#free_pagesObject

Return the count of free pages (free bit is true) on this extent.



108
109
110
# File 'lib/innodb/xdes.rb', line 108

def free_pages
  each_page_status.inject(0) { |sum, p| sum += 1 if p[:free]; sum }
end

#next_addressObject

Return the address of the next list pointer from the list node contained within the XDES entry. This is used by Innodb::List::Xdes to iterate through XDES entries in a list.



127
128
129
# File 'lib/innodb/xdes.rb', line 127

def next_address
  xdes[:list][:next]
end

#prev_addressObject

Return the address of the previous list pointer from the list node contained within the XDES entry. This is used by Innodb::List::Xdes to iterate through XDES entries in a list.



120
121
122
# File 'lib/innodb/xdes.rb', line 120

def prev_address
  xdes[:list][:prev]
end

#read_xdes_entry(page, cursor) ⇒ Object

Read an XDES entry from a cursor.



58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/innodb/xdes.rb', line 58

def read_xdes_entry(page, cursor)
  extent_number = (cursor.position - page.pos_xdes_array) / size_entry
  start_page = page.offset + (extent_number * page.space.pages_per_extent)
  {
    :start_page => start_page,
    :fseg_id    => cursor.get_uint64,
    :this       => {:page => page.offset, :offset => cursor.position},
    :list       => Innodb::List.get_node(cursor),
    :state      => STATES[cursor.get_uint32],
    :bitmap     => cursor.get_bytes(size_bitmap),
  }
end

#size_bitmapObject

Size (in bytes) of the bitmap field in the XDES entry.



48
49
50
# File 'lib/innodb/xdes.rb', line 48

def size_bitmap
  (@page.space.pages_per_extent * BITS_PER_PAGE) / 8
end

#size_entryObject

Size (in bytes) of the an XDES entry.



53
54
55
# File 'lib/innodb/xdes.rb', line 53

def size_entry
  8 + Innodb::List::NODE_SIZE + 4 + size_bitmap
end

#used_pagesObject

Return the count of used pages (free bit is false) on this extent.



113
114
115
# File 'lib/innodb/xdes.rb', line 113

def used_pages
  @page.space.pages_per_extent - free_pages
end

#xdesObject

Return the stored extent descriptor entry.



72
73
74
# File 'lib/innodb/xdes.rb', line 72

def xdes
  @xdes
end