Class: Innodb::Xdes

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

Defined Under Namespace

Classes: Entry, PageStatus

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).

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

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

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

  # 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).
  4 => :fseg,
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(page, cursor) ⇒ Xdes

Returns a new instance of Xdes.



64
65
66
67
# File 'lib/innodb/xdes.rb', line 64

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

Instance Attribute Details

#xdesObject (readonly)

Returns the value of attribute xdes.



51
52
53
# File 'lib/innodb/xdes.rb', line 51

def xdes
  @xdes
end

Instance Method Details

#==(other) ⇒ Object

Compare one Innodb::Xdes to another.



164
165
166
# File 'lib/innodb/xdes.rb', line 164

def ==(other)
  this.page == other.this.page && this.offset == other.this.offset
end

#allocated_to_fseg?Boolean

Return whether this XDES entry is allocated to an fseg (the whole extent then belongs to the fseg).

Returns:

  • (Boolean)


99
100
101
# File 'lib/innodb/xdes.rb', line 99

def allocated_to_fseg?
  fseg_id != 0
end

#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).


118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/innodb/xdes.rb', line 118

def each_page_status
  return enum_for(:each_page_status) unless block_given?

  bitmap.each_byte.with_index do |byte, byte_index|
    (0..3).each do |page_offset|
      page_number = start_page + (byte_index * 4) + page_offset
      page_bits = ((byte >> (page_offset * BITS_PER_PAGE)) & BITMAP_BV_ALL)
      page_status = PageStatus.new(
        free: (page_bits & BITMAP_BV_FREE != 0),
        clean: (page_bits & BITMAP_BV_CLEAN != 0)
      )
      yield page_number, page_status
    end
  end

  nil
end

#free_pagesObject

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



137
138
139
140
141
142
# File 'lib/innodb/xdes.rb', line 137

def free_pages
  each_page_status.inject(0) do |sum, (_page_number, page_status)|
    sum += 1 if page_status.free
    sum
  end
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.



159
160
161
# File 'lib/innodb/xdes.rb', line 159

def next_address
  list.next
end

#page_status(page_number) ⇒ Object

Return the status for a given page. This is relatively inefficient as implemented and could be done better.



105
106
107
108
# File 'lib/innodb/xdes.rb', line 105

def page_status(page_number)
  page_status_array = each_page_status.to_a
  page_status_array[page_number - start_page][1]
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.



152
153
154
# File 'lib/innodb/xdes.rb', line 152

def prev_address
  list.prev
end

#read_xdes_entry(page, cursor) ⇒ Object

Read an XDES entry from a cursor.



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/innodb/xdes.rb', line 80

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)
  cursor.name("xdes[#{extent_number}]") do |c|
    Entry.new(
      offset: c.position,
      start_page: start_page,
      end_page: start_page + page.space.pages_per_extent - 1,
      fseg_id: c.name("fseg_id") { c.read_uint64 },
      this: Innodb::Page::Address.new(page: page.offset, offset: c.position),
      list: c.name("list") { Innodb::List.get_node(c) },
      state: c.name("state") { STATES[c.read_uint32] },
      bitmap: c.name("bitmap") { c.read_bytes(size_bitmap) }
    )
  end
end

#size_bitmapObject

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



70
71
72
# File 'lib/innodb/xdes.rb', line 70

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

#size_entryObject

Size (in bytes) of the an XDES entry.



75
76
77
# File 'lib/innodb/xdes.rb', line 75

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.



145
146
147
# File 'lib/innodb/xdes.rb', line 145

def used_pages
  @page.space.pages_per_extent - free_pages
end