Class: Innodb::Page::FspHdrXdes

Inherits:
Innodb::Page show all
Extended by:
ReadBitsAtOffset
Defined in:
lib/innodb/page/fsp_hdr_xdes.rb

Defined Under Namespace

Classes: EncryptionHeader, Flags, Header, SdiHeader

Constant Summary collapse

FLAGS_PAGE_SIZE_SHIFT =

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

9

Constants inherited from Innodb::Page

PAGE_TYPE, PAGE_TYPE_BY_VALUE, UNDEFINED_PAGE_NUMBER

Instance Attribute Summary

Attributes inherited from Innodb::Page

#space

Class Method Summary collapse

Instance Method Summary collapse

Methods included from ReadBitsAtOffset

read_bits_at_offset

Methods inherited from Innodb::Page

#checksum_crc32, #checksum_crc32?, #checksum_innodb, #checksum_innodb?, #checksum_invalid?, #checksum_type, #checksum_valid?, #corrupt?, #cursor, #default_page_size?, #each_page_body_byte_as_uint8, #each_page_header_byte_as_uint8, #extent_descriptor?, #fil_header, #fil_trailer, handle, #in_doublewrite_buffer?, #initialize, #inspect, #inspect_header_fields, maybe_undefined, #misplaced?, #misplaced_offset?, #misplaced_space?, #name, page_type_by_value, parse, #pos_fil_header, #pos_fil_trailer, #pos_page_body, #pos_partial_page_header, register_specialization, #size, #size_fil_header, #size_fil_trailer, #size_page_body, #size_partial_page_header, specialization_for, specialization_for?, #torn?, undefined?

Constructor Details

This class inherits a constructor from Innodb::Page

Class Method Details

.decode_flags(flags) ⇒ Object

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.



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# 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) ⇒ Object



70
71
72
# 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

Instance Method Details

#dumpObject

Dump the contents of a page for debugging purposes.



259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
# 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_listObject

Iterate through all lists in the file space.



175
176
177
178
179
180
181
# 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.new( offset: pos_fsp_header, length: size_fsp_header, name: :fsp_header, info: "FSP Header" )| ... } ⇒ Object

Yields:



219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
# 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_xdesObject

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



187
188
189
190
191
192
193
194
195
# 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_headerObject



197
198
199
200
201
202
203
204
205
206
207
208
# 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_arrayObject

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



125
126
127
# File 'lib/innodb/page/fsp_hdr_xdes.rb', line 125

def entries_in_xdes_array
  size / space.pages_per_extent
end

#fsp_headerObject

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.



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# 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_headerObject



137
138
139
# File 'lib/innodb/page/fsp_hdr_xdes.rb', line 137

def pos_encryption_header
  pos_xdes_array + size_xdes_array
end

#pos_fsp_headerObject

The FSP header immediately follows the FIL header.



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

def pos_fsp_header
  pos_page_body
end

#pos_sdi_headerObject



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

def pos_sdi_header
  pos_encryption_header + size_encryption_header
end

#pos_xdes_arrayObject

The XDES entry array immediately follows the FSP header.



119
120
121
# File 'lib/innodb/page/fsp_hdr_xdes.rb', line 119

def pos_xdes_array
  pos_fsp_header + size_fsp_header
end

#sdi_headerObject



210
211
212
213
214
215
216
217
# 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_headerObject



141
142
143
# File 'lib/innodb/page/fsp_hdr_xdes.rb', line 141

def size_encryption_header
  3 + 4 + (32 * 2) + 36 + 4 + 4
end

#size_fsp_headerObject

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



114
115
116
# 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_headerObject



149
150
151
# File 'lib/innodb/page/fsp_hdr_xdes.rb', line 149

def size_sdi_header
  8
end

#size_xdes_arrayObject



133
134
135
# File 'lib/innodb/page/fsp_hdr_xdes.rb', line 133

def size_xdes_array
  entries_in_xdes_array * size_xdes_entry
end

#size_xdes_entryObject



129
130
131
# 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