Skip to content

Commit

Permalink
Add new page types for MySQL 8.0, remove :usage key in structure
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremycole committed May 23, 2023
1 parent 0a878dd commit 002611f
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 32 deletions.
25 changes: 12 additions & 13 deletions bin/innodb_space
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,8 @@ def print_index_page_summary(pages)
]

pages.each do |page_number, page|
case page.type
when :INDEX
case
when page.is_a?(Innodb::Page::Index)
puts "%-12i%-8i%-8i%-8i%-8i%-8i" % [
page_number,
page.page_header[:index_id],
Expand All @@ -166,7 +166,7 @@ def print_index_page_summary(pages)
page.free_space,
page.records,
]
when :ALLOCATED
when page.type == :ALLOCATED
puts "%-12i%-8i%-8i%-8i%-8i%-8i" % [page_number, 0, 0, 0, page.size, 0]
end
end
Expand Down Expand Up @@ -429,12 +429,12 @@ def space_index_pages_free_plot(space, start_page)
index_data = { 0 => { x: [], y: [] } }

space.each_page(start_page) do |page_number, page|
case page.type
when :INDEX
case
when page.is_a?(Innodb::Page::Index)
data = (index_data[page.page_header[:index_id]] ||= { x: [], y: [] })
data[:x] << page_number
data[:y] << page.free_space
when :ALLOCATED
when page.type == :ALLOCATED
index_data[0][:x] << page_number
index_data[0][:y] << page.size
end
Expand Down Expand Up @@ -689,10 +689,9 @@ def page_account(innodb_system, space, page_number)

page = space.page(page_number)
page_type = Innodb::Page::PAGE_TYPE[page.type]
puts " Page type is %s (%s, %s)." % [
puts " Page type is %s (%s)." % [
page.type,
page_type[:description],
page_type[:usage],
]

xdes = space.xdes_for_page(page_number)
Expand Down Expand Up @@ -921,7 +920,7 @@ def page_validate(_innodb_system, space, page_number)
end
end

page_is_valid = false if page.type == :INDEX && !page_validate_index(page)
page_is_valid = false if page.is_a?(Innodb::Page::Index) && !page_validate_index(page)

puts "Page %d appears to be %s!" % [
page_number,
Expand All @@ -930,7 +929,7 @@ def page_validate(_innodb_system, space, page_number)
end

def page_directory_summary(_space, page)
usage(1, "Page must be an index page") if page.type != :INDEX
usage(1, "Page must be an index page") unless page.is_a?(Innodb::Page::Index)

puts "%-8s%-8s%-14s%-8s%s" % %w[
slot
Expand Down Expand Up @@ -965,7 +964,7 @@ end

def page_illustrate(page)
width = 64
unknown_page_content = page.type == :INDEX && page.record_describer.nil?
unknown_page_content = page.is_a?(Innodb::Page::Index) && page.record_describer.nil?
blocks = Array.new(page.size, unknown_page_content ? "▞" : " ")
identifiers = {}
identifier_sort = 0
Expand Down Expand Up @@ -1643,7 +1642,7 @@ if innodb_system && @options.table_name && @options.index_name
page = @options.page ? space.page(@options.page) : index.root
elsif @options.page
page = space.page(@options.page)
index = space.index(@options.page) if page&.type == :INDEX && page&.root?
index = space.index(@options.page) if page.is_a?(Innodb::Page::Index) && page&.root?
end

# The non-option argument on the command line is the mode (usually the last,
Expand Down Expand Up @@ -1696,7 +1695,7 @@ if /^record-/.match(mode) && !page
)
end

if /^record-/.match(mode) && page.type != :INDEX
if /^record-/.match(mode) && !page.is_a?(Innodb::Page::Index)
usage(1, "Mode #{mode} may be used only with index pages")
end

Expand Down
10 changes: 6 additions & 4 deletions lib/innodb/index.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ def initialize(space, root_page_number, record_describer = nil)
raise "Page #{root_page_number} couldn't be read" unless @root

# The root page should be an index page.
raise "Page #{root_page_number} is a #{@root.type} page, not an INDEX page" unless @root.type == :INDEX
unless @root.is_a?(Innodb::Page::Index)
raise "Page #{root_page_number} is a #{@root.type} page, not an INDEX page"
end

# The root page should be the only page at its level.
raise "Page #{root_page_number} does not appear to be an index root" if @root.prev || @root.next
Expand Down Expand Up @@ -53,12 +55,12 @@ def node_type(page)

# Internal method used by recurse.
def _recurse(parent_page, page_proc, link_proc, depth = 0)
page_proc.call(parent_page, depth) if page_proc && parent_page.type == :INDEX
page_proc.call(parent_page, depth) if page_proc && parent_page.is_a?(Innodb::Page::Index)

parent_page.each_child_page do |child_page_number, child_min_key|
child_page = page(child_page_number)
child_page.record_describer = record_describer
next unless child_page.type == :INDEX
next unless child_page.is_a?(Innodb::Page::Index)

link_proc&.call(parent_page, child_page, child_min_key, depth + 1)
_recurse(child_page, page_proc, link_proc, depth + 1)
Expand Down Expand Up @@ -143,7 +145,7 @@ def each_fseg_frag_page(fseg)
def each_page_from(page)
return enum_for(:each_page_from, page) unless block_given?

while page && page.type == :INDEX
while page.is_a?(Innodb::Page::Index)
yield page
break unless page.next

Expand Down
95 changes: 81 additions & 14 deletions lib/innodb/page.rb
Original file line number Diff line number Diff line change
Expand Up @@ -202,67 +202,130 @@ def size_page_body
ALLOCATED: {
value: 0,
description: "Freshly allocated",
usage: "page type field has not been initialized",
},
UNDO_LOG: {
value: 2,
description: "Undo log",
usage: "stores previous values of modified records",
},
INODE: {
value: 3,
description: "File segment inode",
usage: "bookkeeping for file segments",
},
IBUF_FREE_LIST: {
value: 4,
description: "Insert buffer free list",
usage: "bookkeeping for insert buffer free space management",
},
IBUF_BITMAP: {
value: 5,
description: "Insert buffer bitmap",
usage: "bookkeeping for insert buffer writes to be merged",
},
SYS: {
value: 6,
description: "System internal",
usage: "used for various purposes in the system tablespace",
},
TRX_SYS: {
value: 7,
description: "Transaction system header",
usage: "bookkeeping for the transaction system in system tablespace",
},
FSP_HDR: {
value: 8,
description: "File space header",
usage: "header page (page 0) for each tablespace file",
},
XDES: {
value: 9,
description: "Extent descriptor",
usage: "header page for subsequent blocks of 16,384 pages",
},
BLOB: {
value: 10,
description: "Uncompressed BLOB",
usage: "externally-stored uncompressed BLOB column data",
},
ZBLOB: {
value: 11,
description: "First compressed BLOB",
usage: "externally-stored compressed BLOB column data, first page",
},
ZBLOB2: {
value: 12,
description: "Subsequent compressed BLOB",
usage: "externally-stored compressed BLOB column data, subsequent page",
},
UNKNOWN: {
value: 13,
description: "Unknown",
},
COMPRESSED: {
value: 14,
description: "Compressed",
},
ENCRYPTED: {
value: 15,
description: "Encrypted",
},
COMPRESSED_AND_ENCRYPTED: {
value: 16,
description: "Compressed and Encrypted",
},
ENCRYPTED_RTREE: {
value: 17,
description: "Encrypted R-tree",
},
SDI_BLOB: {
value: 18,
description: "Uncompressed SDI BLOB",
},
SDI_ZBLOB: {
value: 19,
description: "Compressed SDI BLOB",
},
LEGACY_DBLWR: {
value: 20,
description: "Legacy doublewrite buffer",
},
RSEG_ARRAY: {
value: 21,
description: "Rollback Segment Array",
},
LOB_INDEX: {
value: 22,
description: "Index of uncompressed LOB",
},
LOB_DATA: {
value: 23,
description: "Data of uncompressed LOB",
},
LOB_FIRST: {
value: 24,
description: "First page of an uncompressed LOB",
},
ZLOB_FIRST: {
value: 25,
description: "First page of a compressed LOB",
},
ZLOB_DATA: {
value: 26,
description: "Data of compressed LOB",
},
ZLOB_INDEX: {
value: 27,
description: "Index of compressed LOB",
},
ZLOB_FRAG: {
value: 28,
description: "Fragment of compressed LOB",
},
ZLOB_FRAG_ENTRY: {
value: 29,
description: "Index of fragment for compressed LOB",
},
SDI: {
value: 17_853,
description: "Serialized Dictionary Information",
},
RTREE: {
value: 17_854,
description: "R-tree index",
},
INDEX: {
value: 17_855,
description: "B+Tree index",
usage: "table and index data stored in B+Tree structure",
},
}.freeze

Expand All @@ -282,6 +345,10 @@ def self.maybe_undefined(page_number)
page_number unless undefined?(page_number)
end

def self.page_type_by_value(value)
PAGE_TYPE_BY_VALUE[value] || value
end

# Return the "fil" header from the page, which is common for all page types.
def fil_header
@fil_header ||= cursor(pos_fil_header).name("fil_header") do |c|
Expand All @@ -291,7 +358,7 @@ def fil_header
prev: c.name("prev") { Innodb::Page.maybe_undefined(c.read_uint32) },
next: c.name("next") { Innodb::Page.maybe_undefined(c.read_uint32) },
lsn: c.name("lsn") { c.read_uint64 },
type: c.name("type") { PAGE_TYPE_BY_VALUE[c.read_uint16] },
type: c.name("type") { Innodb::Page.page_type_by_value(c.read_uint16) },
flush_lsn: c.name("flush_lsn") { c.read_uint64 },
space_id: c.name("space_id") { c.read_uint32 }
)
Expand Down
2 changes: 1 addition & 1 deletion lib/innodb/space.rb
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ def each_index_root_page_number
# for IBD files, if they haven't added indexes online.
(3...@pages).each do |page_number|
page = page(page_number)
yield page_number if page.type == :INDEX && page.root?
yield page_number if page.is_a?(Innodb::Page::Index) && page.root?
end
end

Expand Down

0 comments on commit 002611f

Please sign in to comment.