class Innodb::Page::FspHdrXdes

Constants

EncryptionHeader
FLAGS_PAGE_SIZE_SHIFT

A value added to the adjusted exponent stored in the page size field of the flags in the FSP header.

Flags
SdiHeader

Public Class Methods

decode_flags(flags) click to toggle source

Decode the “flags” field in the FSP header, returning a hash of useful decodings of the flags (based on MySQl 5.6 definitions). The flags are:

Offset Size Description 0 1 Post-Antelope Flag. 1 4 Compressed Page Size (zip_size). This is stored as a

power of 2, minus 9. Since 0 is reserved to mean "not
compressed", the minimum value is 1, thus making the
smallest page size 1024 (2 ** (9 + 1)).

5 1 Atomic Blobs Flag. 6 4 System Page Size (innodb_page_size, UNIV_PAGE_SIZE).

The setting of the system page size when the tablespace
was created, stored in the same format as the compressed
page size above.

10 1 Data Directory Flag.

# File lib/innodb/page/fsp_hdr_xdes.rb, line 90
def self.decode_flags(flags)
  system_page_size =
    shift_page_size(read_bits_at_offset(flags, 4, 6)) ||
    Innodb::Space::DEFAULT_PAGE_SIZE
  compressed_page_size = shift_page_size(read_bits_at_offset(flags, 4, 1))

  Flags.new(
    system_page_size: system_page_size,
    compressed: compressed_page_size ? false : true,
    page_size: compressed_page_size || system_page_size,
    post_antelope: read_bits_at_offset(flags, 1, 0) == 1,
    atomic_blobs: read_bits_at_offset(flags, 1, 5) == 1,
    data_directory: read_bits_at_offset(flags, 1, 10) == 1,
    value: flags
  )
end
shift_page_size(page_size_shifted) click to toggle source
# File lib/innodb/page/fsp_hdr_xdes.rb, line 70
def self.shift_page_size(page_size_shifted)
  (1 << (FLAGS_PAGE_SIZE_SHIFT + page_size_shifted)) if page_size_shifted != 0
end

Public Instance Methods

dump() click to toggle source

Dump the contents of a page for debugging purposes.

Calls superclass method Innodb::Page#dump
# File lib/innodb/page/fsp_hdr_xdes.rb, line 259
def dump
  super

  puts "fsp header:"
  pp fsp_header
  puts

  puts "xdes entries:"
  each_xdes do |xdes|
    pp xdes
  end
  puts

  puts "encryption header:"
  pp encryption_header
  puts

  puts "serialized dictionary information header:"
  pp sdi_header
  puts
end
each_list() { |key, value| ... } click to toggle source

Iterate through all lists in the file space.

# File lib/innodb/page/fsp_hdr_xdes.rb, line 175
def each_list
  return enum_for(:each_list) unless block_given?

  fsp_header.to_h.each do |key, value|
    yield key, value if value.is_a?(Innodb::List)
  end
end
each_region() { |region( offset: pos_fsp_header, length: size_fsp_header, name: :fsp_header, info: "FSP Header"| ... } click to toggle source
Calls superclass method Innodb::Page#each_region
# File lib/innodb/page/fsp_hdr_xdes.rb, line 219
def each_region(&block)
  return enum_for(:each_region) unless block_given?

  super

  yield Region.new(
    offset: pos_fsp_header,
    length: size_fsp_header,
    name: :fsp_header,
    info: "FSP Header"
  )

  each_xdes do |xdes|
    state = xdes.state || "unused"
    yield Region.new(
      offset: xdes.offset,
      length: size_xdes_entry,
      name: :"xdes_#{state}",
      info: "Extent Descriptor (#{state})"
    )
  end

  yield Region.new(
    offset: pos_encryption_header,
    length: size_encryption_header,
    name: :encryption_header,
    info: "Encryption Header"
  )

  yield Region.new(
    offset: pos_sdi_header,
    length: size_sdi_header,
    name: :sdi_header,
    info: "SDI Header"
  )

  nil
end
each_xdes() { |xdes| ... } click to toggle source

Iterate through all XDES entries in order. This is useful for debugging, but each of these entries is actually a node in some other list. The state field in the XDES entry indicates which type of list it is present in, although not necessarily which list (e.g. :fseg).

# File lib/innodb/page/fsp_hdr_xdes.rb, line 187
def each_xdes
  return enum_for(:each_xdes) unless block_given?

  cursor(pos_xdes_array).name("xdes_array") do |c|
    entries_in_xdes_array.times do
      yield Innodb::Xdes.new(self, c)
    end
  end
end
encryption_header() click to toggle source
# File lib/innodb/page/fsp_hdr_xdes.rb, line 197
def encryption_header
  @encryption_header ||= cursor(pos_encryption_header).name("encryption_header") do |c|
    EncryptionHeader.new(
      magic: c.name("magic") { c.read_bytes(3) },
      master_key_id: c.name("master_key_id") { c.read_uint32 },
      key: c.name("key") { c.read_bytes(32) },
      iv: c.name("iv") { c.read_bytes(32) },
      server_uuid: c.name("server_uuid") { c.read_string(36) },
      checksum: c.name("checksum") { c.read_uint32 }
    )
  end
end
entries_in_xdes_array() click to toggle source

The number of entries in the XDES array. Defined as page size divided by extent size.

# File lib/innodb/page/fsp_hdr_xdes.rb, line 125
def entries_in_xdes_array
  size / space.pages_per_extent
end
fsp_header() click to toggle source

Read the FSP (filespace) header, which contains a few counters and flags, as well as list base nodes for each list maintained in the filespace.

# File lib/innodb/page/fsp_hdr_xdes.rb, line 155
def fsp_header
  @fsp_header ||= cursor(pos_fsp_header).name("fsp") do |c|
    Header.new(
      space_id: c.name("space_id") { c.read_uint32 },
      unused: c.name("unused") { c.read_uint32 },
      size: c.name("size") { c.read_uint32 },
      free_limit: c.name("free_limit") { c.read_uint32 },
      flags: c.name("flags") { self.class.decode_flags(c.read_uint32) },
      frag_n_used: c.name("frag_n_used") { c.read_uint32 },
      free: c.name("list[free]") { Innodb::List::Xdes.new(@space, Innodb::List.get_base_node(c)) },
      free_frag: c.name("list[free_frag]") { Innodb::List::Xdes.new(@space, Innodb::List.get_base_node(c)) },
      full_frag: c.name("list[full_frag]") { Innodb::List::Xdes.new(@space, Innodb::List.get_base_node(c)) },
      first_unused_seg: c.name("first_unused_seg") { c.read_uint64 },
      full_inodes: c.name("list[full_inodes]") { Innodb::List::Inode.new(@space, Innodb::List.get_base_node(c)) },
      free_inodes: c.name("list[free_inodes]") { Innodb::List::Inode.new(@space, Innodb::List.get_base_node(c)) }
    )
  end
end
pos_encryption_header() click to toggle source
# File lib/innodb/page/fsp_hdr_xdes.rb, line 137
def pos_encryption_header
  pos_xdes_array + size_xdes_array
end
pos_fsp_header() click to toggle source

The FSP header immediately follows the FIL header.

# File lib/innodb/page/fsp_hdr_xdes.rb, line 108
def pos_fsp_header
  pos_page_body
end
pos_sdi_header() click to toggle source
# File lib/innodb/page/fsp_hdr_xdes.rb, line 145
def pos_sdi_header
  pos_encryption_header + size_encryption_header
end
pos_xdes_array() click to toggle source

The XDES entry array immediately follows the FSP header.

# File lib/innodb/page/fsp_hdr_xdes.rb, line 119
def pos_xdes_array
  pos_fsp_header + size_fsp_header
end
sdi_header() click to toggle source
# File lib/innodb/page/fsp_hdr_xdes.rb, line 210
def sdi_header
  @sdi_header ||= cursor(pos_sdi_header).name("sdi_header") do |c|
    SdiHeader.new(
      version: c.name("version") { c.read_uint32 },
      root_page_number: c.name("root_page_number") { c.read_uint32 }
    )
  end
end
size_encryption_header() click to toggle source
# File lib/innodb/page/fsp_hdr_xdes.rb, line 141
def size_encryption_header
  3 + 4 + (32 * 2) + 36 + 4 + 4
end
size_fsp_header() click to toggle source

The FSP header contains six 32-bit integers, one 64-bit integer, and 5 list base nodes.

# File lib/innodb/page/fsp_hdr_xdes.rb, line 114
def size_fsp_header
  ((4 * 6) + (1 * 8) + (5 * Innodb::List::BASE_NODE_SIZE))
end
size_sdi_header() click to toggle source
# File lib/innodb/page/fsp_hdr_xdes.rb, line 149
def size_sdi_header
  8
end
size_xdes_array() click to toggle source
# File lib/innodb/page/fsp_hdr_xdes.rb, line 133
def size_xdes_array
  entries_in_xdes_array * size_xdes_entry
end
size_xdes_entry() click to toggle source
# File lib/innodb/page/fsp_hdr_xdes.rb, line 129
def size_xdes_entry
  @size_xdes_entry ||= Innodb::Xdes.new(self, cursor(pos_xdes_array)).size_entry
end