innodb_ruby 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
File without changes
data/bin/innodb_space ADDED
@@ -0,0 +1,306 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "getoptlong"
4
+ require "ostruct"
5
+ require "pp"
6
+ require "innodb"
7
+
8
+ def space_summary(space)
9
+ puts "%-12s%-20s%-12s%-12s%-20s" % [
10
+ "page",
11
+ "type",
12
+ "prev",
13
+ "next",
14
+ "lsn",
15
+ ]
16
+
17
+ space.each_page do |page_number, page|
18
+ puts "%-12i%-20s%-12i%-12i%-20i" % [
19
+ page_number,
20
+ page.type,
21
+ page.prev,
22
+ page.next,
23
+ page.lsn,
24
+ ]
25
+ end
26
+ end
27
+
28
+ def space_index_pages_summary(space)
29
+ puts "%-12s%-8s%-8s%-8s%-8s%-8s" % [
30
+ "page",
31
+ "index",
32
+ "level",
33
+ "data",
34
+ "free",
35
+ "records",
36
+ ]
37
+
38
+ space.each_page do |page_number, page|
39
+ case page.type
40
+ when :INDEX
41
+ puts "%-12i%-8i%-8i%-8i%-8i%-8i" % [
42
+ page_number,
43
+ page.ph[:index_id],
44
+ page.ph[:level],
45
+ page.record_space,
46
+ page.free_space,
47
+ page.ph[:n_recs],
48
+ ]
49
+ when :ALLOCATED
50
+ puts "%-12i%-8i%-8i%-8i%-8i%-8i" % [ page_number, 0, 0, 0, page.size, 0 ]
51
+ end
52
+ end
53
+ end
54
+
55
+ def index_recurse(index)
56
+ index.recurse(
57
+ lambda do |page, depth|
58
+ puts "%s%s %i: %i records, %i bytes" % [
59
+ " " * depth,
60
+ page.level == 0 ? "LEAF" : "NODE",
61
+ page.offset,
62
+ page.page_header[:n_recs],
63
+ page.record_space,
64
+ ]
65
+ if page.level == 0
66
+ page.each_record do |record|
67
+ puts "%sRECORD: (%s) -> (%s)" % [
68
+ " " * (depth+1),
69
+ record[:key].join(", "),
70
+ record[:row].join(", "),
71
+ ]
72
+ end
73
+ end
74
+ end,
75
+ lambda do |parent_page, child_page, child_min_key, depth|
76
+ puts "%sLINK %i -> %i: %s records >= (%s)" % [
77
+ " " * depth,
78
+ parent_page.offset,
79
+ child_page.offset,
80
+ child_page.page_header[:n_recs],
81
+ child_min_key.join(", "),
82
+ ]
83
+ end
84
+ )
85
+ end
86
+
87
+ def index_digraph(index)
88
+ puts "digraph btree {"
89
+ puts " rankdir = LR;"
90
+ puts " ranksep = 2.0;"
91
+ index.recurse(
92
+ lambda do |page, depth|
93
+ label = "<page>Page %i|(%i records)" % [
94
+ page.offset,
95
+ page.page_header[:n_recs],
96
+ ]
97
+ page.each_child_page do |child_page_number, child_key|
98
+ label += "|<dir_%i>(%s)" % [
99
+ child_page_number,
100
+ child_key.join(", "),
101
+ ]
102
+ end
103
+ puts " %spage_%i [ shape = \"record\"; label = \"%s\"; ];" % [
104
+ " " * depth,
105
+ page.offset,
106
+ label,
107
+ ]
108
+ end,
109
+ lambda do |parent_page, child_page, child_key, depth|
110
+ puts " %spage_%i:dir_%i -> page_%i:page:nw;" % [
111
+ " " * depth,
112
+ parent_page.offset,
113
+ child_page.offset,
114
+ child_page.offset,
115
+ ]
116
+ end
117
+ )
118
+ puts "}"
119
+ end
120
+
121
+ def index_level_summary(index, levels)
122
+ puts "%-8s%-8s%-8s%-8s%-8s%-8s%-8s" % [
123
+ "page",
124
+ "index",
125
+ "level",
126
+ "data",
127
+ "free",
128
+ "records",
129
+ "min_key",
130
+ ]
131
+
132
+ levels.each do |level|
133
+ index.each_page_at_level(level) do |page|
134
+ puts "%-8i%-8i%-8i%-8i%-8i%-8i%s" % [
135
+ page.offset,
136
+ page.ph[:index_id],
137
+ page.ph[:level],
138
+ page.record_space,
139
+ page.free_space,
140
+ page.ph[:n_recs],
141
+ page.first_record[:key].join("|"),
142
+ ]
143
+ end
144
+ end
145
+ end
146
+
147
+ def usage(exit_code, message = nil)
148
+ print "Error: #{message}\n" unless message.nil?
149
+
150
+ print <<'END_OF_USAGE'
151
+
152
+ Usage: innodb_space -f <file> [-p <page>] [-l <level>] <mode> [<mode>, ...]
153
+
154
+ --help, -?
155
+ Print this usage text.
156
+
157
+ --file, -f <file>
158
+ Load the tablespace file <file>.
159
+
160
+ --page, -p <page>
161
+ Operate on the page <page>; may be specified more than once.
162
+
163
+ --level, -l <level>
164
+ Operate on the level <level>; may be specified more than once.
165
+
166
+ --require, -r <file>
167
+ Use Ruby's "require" to load the file <file>. This is useful for loading
168
+ classes with record describers.
169
+
170
+ --describer, -d <describer>
171
+ Use the named record describer to parse records in index pages.
172
+
173
+ The following modes are supported:
174
+
175
+ page-dump
176
+ Dump the contents of the page, using the Ruby pp ("pretty-print") module.
177
+
178
+ space-summary
179
+ Summarize all pages within a tablespace.
180
+
181
+ space-index-pages-summary
182
+ Summarize all "INDEX" pages within a tablespace. This is useful to analyze
183
+ page fill rates and record counts per page. In addition to "INDEX" pages,
184
+ "ALLOCATED" pages are also printed and assumed to be completely empty.
185
+
186
+ index-recurse
187
+ Recurse an index, starting at the root (which must be provided in the first
188
+ --page/-p argument), printing the node pages, node pointers (links), leaf
189
+ pages. A record describer must be provided with the --describer/-d argument
190
+ to recurse indexes (in order to parse node pages).
191
+
192
+ index-digraph
193
+ Recurse an index as index-recurse does, but print a dot-compatible digraph
194
+ instead of a human-readable summary.
195
+
196
+ index-level-summary
197
+ Print a summary of all pages at a given level (provided with the --level/-l
198
+ argument) in an index.
199
+
200
+ END_OF_USAGE
201
+
202
+ exit exit_code
203
+ end
204
+
205
+ @options = OpenStruct.new
206
+ @options.file = nil
207
+ @options.pages = []
208
+ @options.levels = []
209
+ @options.describer = nil
210
+
211
+ getopt_options = [
212
+ [ "--help", "-?", GetoptLong::NO_ARGUMENT ],
213
+ [ "--file", "-f", GetoptLong::REQUIRED_ARGUMENT ],
214
+ [ "--page", "-p", GetoptLong::REQUIRED_ARGUMENT ],
215
+ [ "--level", "-l", GetoptLong::REQUIRED_ARGUMENT ],
216
+ [ "--require", "-r", GetoptLong::REQUIRED_ARGUMENT ],
217
+ [ "--describer", "-d", GetoptLong::REQUIRED_ARGUMENT ],
218
+ ]
219
+
220
+ getopt = GetoptLong.new(*getopt_options)
221
+
222
+ getopt.each do |opt, arg|
223
+ case opt
224
+ when "--help"
225
+ usage 0
226
+ when "--mode"
227
+ @options.mode = arg
228
+ when "--file"
229
+ @options.file = arg
230
+ when "--page"
231
+ @options.pages << arg.to_i
232
+ when "--level"
233
+ @options.levels << arg.to_i
234
+ when "--require"
235
+ require arg
236
+ when "--describer"
237
+ @options.describer = arg
238
+ end
239
+ end
240
+
241
+ unless @options.file
242
+ usage 1, "File must be provided with -f argument"
243
+ end
244
+
245
+ space = Innodb::Space.new(@options.file)
246
+
247
+ if @options.describer
248
+ space.record_describer = Innodb::RecordDescriber.const_get(@options.describer)
249
+ end
250
+
251
+ if ARGV.empty?
252
+ usage 1, "At least one mode should be provided"
253
+ end
254
+
255
+ ARGV.each do |mode|
256
+ case mode
257
+ when "page-dump"
258
+ if @options.pages.empty?
259
+ usage 1, "Page numbers to dump must be provided"
260
+ end
261
+
262
+ @options.pages.each do |page|
263
+ space.page(page).dump
264
+ end
265
+ when "space-summary"
266
+ space_summary(space)
267
+ when "space-index-pages-summary"
268
+ space_index_pages_summary(space)
269
+ when "index-recurse"
270
+ unless space.record_describer
271
+ usage 1, "Record describer necessary for index recursion"
272
+ end
273
+
274
+ if @options.pages.empty?
275
+ usage 1, "Page number of index root must be provided"
276
+ end
277
+
278
+ @options.pages.each do |page|
279
+ index_recurse(space.index(page))
280
+ end
281
+ when "index-digraph"
282
+ unless space.record_describer
283
+ usage 1, "Record describer necessary for index recursion"
284
+ end
285
+
286
+ if @options.pages.empty?
287
+ usage 1, "Page number of index root must be provided"
288
+ end
289
+
290
+ @options.pages.each do |page|
291
+ index_digraph(space.index(page))
292
+ end
293
+ when "index-level-summary"
294
+ unless space.record_describer
295
+ usage 1, "Record describer necessary for index recursion"
296
+ end
297
+
298
+ if @options.pages.empty?
299
+ usage 1, "Page number of index root must be provided"
300
+ end
301
+
302
+ index_level_summary(space.index(@options.pages.first), @options.levels)
303
+ else
304
+ usage 1, "Unknown mode: #{mode}"
305
+ end
306
+ end
data/lib/innodb.rb CHANGED
@@ -6,6 +6,7 @@ require "innodb/page"
6
6
  require "innodb/page/fsp_hdr_xdes"
7
7
  require "innodb/page/inode"
8
8
  require "innodb/page/index"
9
+ require "innodb/record_describer"
9
10
  require "innodb/space"
10
11
  require "innodb/index"
11
12
  require "innodb/log_block"
data/lib/innodb/index.rb CHANGED
@@ -32,7 +32,7 @@ class Innodb::Index
32
32
 
33
33
  parent_page.each_child_page do |child_page_number, child_min_key|
34
34
  child_page = @space.page(child_page_number)
35
- child_page.record_formatter = @space.record_formatter
35
+ child_page.record_describer = @space.record_describer
36
36
  if child_page.type == :INDEX
37
37
  if link_proc
38
38
  link_proc.call(parent_page, child_page, child_min_key, depth+1)
@@ -76,7 +76,7 @@ class Innodb::Index
76
76
 
77
77
  # Iterate through all records on all leaf pages in ascending order.
78
78
  def each_record
79
- each_leaf_page do |page|
79
+ each_page_at_level(0) do |page|
80
80
  page.each_record do |record|
81
81
  yield record
82
82
  end
data/lib/innodb/log.rb CHANGED
@@ -16,10 +16,14 @@ class Innodb::Log
16
16
 
17
17
  # Open a log file.
18
18
  def initialize(file)
19
- @file = File.open(file)
20
- @size = @file.stat.size
21
- @blocks = ((@size - DATA_START) / Innodb::LogBlock::BLOCK_SIZE)
19
+ @name = file
20
+ File.open(@name) do |log|
21
+ @size = log.stat.size
22
+ @blocks = ((@size - DATA_START) / Innodb::LogBlock::BLOCK_SIZE)
23
+ end
22
24
  end
25
+
26
+ attr_reader :blocks
23
27
 
24
28
  # Return a log block with a given block number as an InnoDB::LogBlock object.
25
29
  # Blocks are numbered after the log file header, starting from 0.
@@ -27,9 +31,11 @@ class Innodb::Log
27
31
  offset = DATA_START + (block_number.to_i * Innodb::LogBlock::BLOCK_SIZE)
28
32
  return nil unless offset < @size
29
33
  return nil unless (offset + Innodb::LogBlock::BLOCK_SIZE) <= @size
30
- @file.seek(offset)
31
- block_data = @file.read(Innodb::LogBlock::BLOCK_SIZE)
32
- Innodb::LogBlock.new(block_data)
34
+ File.open(@name) do |log|
35
+ log.seek(offset)
36
+ block_data = log.read(Innodb::LogBlock::BLOCK_SIZE)
37
+ Innodb::LogBlock.new(block_data)
38
+ end
33
39
  end
34
40
 
35
41
  # Iterate through all log blocks, returning the block number and an
@@ -57,7 +57,7 @@ class Innodb::LogBlock
57
57
  @header ||= begin
58
58
  c = cursor(HEADER_START)
59
59
  {
60
- :block => c.get_uint32,
60
+ :block => c.get_uint32 & (2**31-1),
61
61
  :data_length => c.get_uint16,
62
62
  :first_rec_group => c.get_uint16,
63
63
  :checkpoint_no => c.get_uint32,
@@ -143,7 +143,7 @@ class Innodb::LogBlock
143
143
  end
144
144
 
145
145
  SINGLE_RECORD_MASK = 0x80
146
- RECORD_TYPE_MASK = 0x7f
146
+ RECORD_TYPE_MASK = 0x7f
147
147
 
148
148
  # Return the log record. (This is mostly unimplemented.)
149
149
  def record
@@ -153,7 +153,7 @@ class Innodb::LogBlock
153
153
  type_and_flag = c.get_uint8
154
154
  type = type_and_flag & RECORD_TYPE_MASK
155
155
  type = RECORD_TYPES[type] || type
156
- single_record = (type_and_flag & SINGLE_RECORD_MASK) == SINGLE_RECORD_MASK
156
+ single_record = (type_and_flag & SINGLE_RECORD_MASK) > 0
157
157
  {
158
158
  :type => type,
159
159
  :single_record => single_record,
data/lib/innodb/page.rb CHANGED
@@ -126,13 +126,18 @@ class Innodb::Page
126
126
  fil_header[:next]
127
127
  end
128
128
 
129
+ # A helper function to return the LSN, for easier access.
130
+ def lsn
131
+ fil_header[:lsn]
132
+ end
133
+
129
134
  # Dump the contents of a page for debugging purposes.
130
135
  def dump
131
- puts
132
136
  puts "#{self}:"
133
-
134
137
  puts
138
+
135
139
  puts "fil header:"
136
140
  pp fil_header
141
+ puts
137
142
  end
138
143
  end
@@ -62,15 +62,15 @@ class Innodb::Page::FspHdrXdes < Innodb::Page
62
62
  def dump
63
63
  super
64
64
 
65
- puts
66
65
  puts "fsp header:"
67
66
  pp fsp_header
68
-
69
67
  puts
68
+
70
69
  puts "xdes entries:"
71
70
  each_xdes do |xdes|
72
71
  pp xdes
73
72
  end
73
+ puts
74
74
  end
75
75
  end
76
76
 
@@ -1,5 +1,5 @@
1
1
  class Innodb::Page::Index < Innodb::Page
2
- attr_accessor :record_formatter
2
+ attr_accessor :record_describer
3
3
 
4
4
  # Return the byte offset of the start of the "index" page header, which
5
5
  # immediately follows the "fil" header.
@@ -229,8 +229,8 @@ class Innodb::Page::Index < Innodb::Page
229
229
 
230
230
  # Return (and cache) the record format provided by an external class.
231
231
  def record_format
232
- if record_formatter
233
- @record_format ||= record_formatter.format(self)
232
+ if record_describer
233
+ @record_format ||= record_describer.cursor_sendable_description(self)
234
234
  end
235
235
  end
236
236
 
@@ -318,11 +318,10 @@ class Innodb::Page::Index < Innodb::Page
318
318
  def dump
319
319
  super
320
320
 
321
- puts
322
321
  puts "page header:"
323
322
  pp page_header
324
-
325
323
  puts
324
+
326
325
  puts "sizes:"
327
326
  puts " %-15s%5i" % [ "header", header_space ]
328
327
  puts " %-15s%5i" % [ "trailer", trailer_space ]
@@ -334,17 +333,18 @@ class Innodb::Page::Index < Innodb::Page
334
333
  "per record",
335
334
  (page_header[:n_recs] > 0) ? (record_space / page_header[:n_recs]) : 0
336
335
  ]
337
-
338
336
  puts
337
+
339
338
  puts "system records:"
340
339
  pp infimum
341
340
  pp supremum
342
-
343
341
  puts
342
+
344
343
  puts "records:"
345
344
  each_record do |rec|
346
345
  pp rec
347
346
  end
347
+ puts
348
348
  end
349
349
  end
350
350
 
@@ -35,9 +35,9 @@ class Innodb::Page::Inode < Innodb::Page
35
35
  def dump
36
36
  super
37
37
 
38
- puts
39
38
  puts "inode header:"
40
39
  pp inode_header
40
+ puts
41
41
  end
42
42
  end
43
43
 
@@ -0,0 +1 @@
1
+ class Innodb::RecordDescriber; end
data/lib/innodb/space.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # An InnoDB tablespace file, which can be either a multi-table ibdataN file
2
2
  # or a single-table "innodb_file_per_table" .ibd file.
3
3
  class Innodb::Space
4
- attr_accessor :record_formatter
4
+ attr_accessor :record_describer
5
5
 
6
6
  # Currently only 16kB InnoDB pages are supported.
7
7
  PAGE_SIZE = 16384
@@ -11,7 +11,7 @@ class Innodb::Space
11
11
  @file = File.open(file)
12
12
  @size = @file.stat.size
13
13
  @pages = (@size / PAGE_SIZE)
14
- @record_formatter = nil
14
+ @record_describer = nil
15
15
  end
16
16
 
17
17
  # Get an Innodb::Page object for a specific page by page number.
@@ -24,12 +24,17 @@ class Innodb::Space
24
24
  this_page = Innodb::Page.parse(page_data)
25
25
 
26
26
  if this_page.type == :INDEX
27
- this_page.record_formatter = @record_formatter
27
+ this_page.record_describer = @record_describer
28
28
  end
29
29
 
30
30
  this_page
31
31
  end
32
32
 
33
+ # Get an Innodb::Index object for a specific index by root page number.
34
+ def index(root_page_number)
35
+ Innodb::Index.new(self, root_page_number)
36
+ end
37
+
33
38
  # Iterate through all pages in a tablespace, returning the page number
34
39
  # and an Innodb::Page object for each one.
35
40
  def each_page
@@ -1,3 +1,3 @@
1
1
  module Innodb
2
- VERSION = "0.5.1"
2
+ VERSION = "0.6.0"
3
3
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: innodb_ruby
3
3
  version: !ruby/object:Gem::Version
4
- hash: 9
4
+ hash: 7
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 5
9
- - 1
10
- version: 0.5.1
8
+ - 6
9
+ - 0
10
+ version: 0.6.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Jeremy Cole
@@ -15,14 +15,14 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-11-29 00:00:00 Z
18
+ date: 2012-12-01 00:00:00 Z
19
19
  dependencies: []
20
20
 
21
21
  description: Library for parsing InnoDB data files in Ruby
22
22
  email: jeremy@jcole.us
23
23
  executables:
24
- - innodb_dump_log
25
- - innodb_dump_space
24
+ - innodb_log
25
+ - innodb_space
26
26
  extensions: []
27
27
 
28
28
  extra_rdoc_files: []
@@ -38,10 +38,11 @@ files:
38
38
  - lib/innodb/page/fsp_hdr_xdes.rb
39
39
  - lib/innodb/page/index.rb
40
40
  - lib/innodb/page/inode.rb
41
+ - lib/innodb/record_describer.rb
41
42
  - lib/innodb/space.rb
42
43
  - lib/innodb/version.rb
43
- - bin/innodb_dump_log
44
- - bin/innodb_dump_space
44
+ - bin/innodb_log
45
+ - bin/innodb_space
45
46
  homepage: http://jcole.us/
46
47
  licenses: []
47
48
 
@@ -1,189 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "pp"
4
- require "innodb"
5
-
6
- class EdgesRecordFormatter
7
- def format(page)
8
- bytes_per_record = (page.record_space / page.page_header[:n_recs])
9
- case
10
- when [48, 26].include?(bytes_per_record) # Clustered Key
11
- {
12
- # PRIMARY KEY (source_id, state, position)
13
- :type => :clustered,
14
- :key => [
15
- [:get_uint64], # source_id
16
- [:get_i_sint8], # state
17
- [:get_i_sint64], # position
18
- ],
19
- :row => [
20
- [:get_uint32], # updated_at
21
- [:get_uint64], # destination_id
22
- [:get_uint8], # count
23
- ],
24
- }
25
- when [30, 34].include?(bytes_per_record) # Secondary Key
26
- {
27
- # INDEX (source_id, destination_id)
28
- :type => :secondary,
29
- :key => [
30
- [:get_uint64], # source_id
31
- [:get_uint64], # destination_id
32
- ],
33
- # PKV ([source_id], state, position)
34
- :row => [
35
- [:get_i_sint8], # state
36
- [:get_i_sint64], # position
37
- ],
38
- }
39
- end
40
- end
41
- end
42
-
43
- class PageSplitTestFormatter
44
- def format(page)
45
- {
46
- # PRIMARY KEY (id)
47
- :type => :clustered,
48
- :key => [
49
- [:get_uint64], # id
50
- ],
51
- :row => [],
52
- }
53
- end
54
- end
55
-
56
- def digraph_index(index)
57
- puts "digraph btree {"
58
- puts " rankdir = LR;"
59
- puts " ranksep = 2.0;"
60
- index.recurse(
61
- lambda do |page, depth|
62
- if true #page.level != 0
63
- label = "<page>Page %i|(%i records)" % [
64
- page.offset,
65
- page.page_header[:n_recs],
66
- ]
67
- page.each_child_page do |child_page_number, child_key|
68
- label += "|<dir_%i>(%s)" % [
69
- child_page_number,
70
- child_key.join(", "),
71
- ]
72
- end
73
- puts " %spage_%i [ shape = \"record\"; label = \"%s\"; ];" % [
74
- " " * depth,
75
- page.offset,
76
- label,
77
- ]
78
- end
79
- end,
80
- lambda do |parent_page, child_page, child_key, depth|
81
- if true #child_page.level > 0
82
- puts " %spage_%i:dir_%i -> page_%i:page:nw;" % [
83
- " " * depth,
84
- parent_page.offset,
85
- child_page.offset,
86
- child_page.offset,
87
- ]
88
- end
89
- end
90
- )
91
- puts "}"
92
- end
93
-
94
- def recurse_index(index)
95
- index.recurse(
96
- lambda do |page, depth|
97
- puts "%s%s %i: %i records, %i bytes" % [
98
- " " * depth,
99
- page.level == 0 ? "LEAF" : "NODE",
100
- page.offset,
101
- page.page_header[:n_recs],
102
- page.record_space,
103
- ]
104
- if page.level == 0
105
- page.each_record do |record|
106
- puts "%sRECORD: (%s) -> (%s)" % [
107
- " " * (depth+1),
108
- record[:key].join(", "),
109
- record[:row].join(", "),
110
- ]
111
- end
112
- end
113
- end,
114
- lambda do |parent_page, child_page, child_min_key, depth|
115
- puts "%sLINK %i -> %i: %s records >= (%s)" % [
116
- " " * depth,
117
- parent_page.offset,
118
- child_page.offset,
119
- child_page.page_header[:n_recs],
120
- child_min_key.join(", "),
121
- ]
122
- end
123
- )
124
- end
125
-
126
- def dump_space(space)
127
- puts "%-8s%-8s%-8s%-8s%-8s%-8s" % [
128
- "page",
129
- "index",
130
- "level",
131
- "data",
132
- "free",
133
- "records",
134
- ]
135
-
136
- space.each_page do |page_number, page|
137
- case page.type
138
- when :INDEX
139
- puts "%-8i%-8i%-8i%-8i%-8i%-8i" % [
140
- page_number,
141
- page.ph[:index_id],
142
- page.ph[:level],
143
- page.record_space,
144
- page.free_space,
145
- page.ph[:n_recs],
146
- ]
147
- when :ALLOCATED
148
- puts "%-8i%-8i%-8i%-8i%-8i%-8i" % [ page_number, 0, 0, 0, Innodb::Space::PAGE_SIZE, 0 ]
149
- end
150
- end
151
- end
152
-
153
- def dump_index_level(index, level)
154
- puts "%-8s%-8s%-8s%-8s%-8s%-8s%-8s" % [
155
- "page",
156
- "index",
157
- "level",
158
- "data",
159
- "free",
160
- "records",
161
- "min_key",
162
- ]
163
-
164
- index.each_page_at_level(level) do |page|
165
- puts "%-8i%-8i%-8i%-8i%-8i%-8i%s" % [
166
- page.offset,
167
- page.ph[:index_id],
168
- page.ph[:level],
169
- page.record_space,
170
- page.free_space,
171
- page.ph[:n_recs],
172
- page.first_record[:key].join("|"),
173
- ]
174
- end
175
- end
176
-
177
- file, page_number = ARGV.shift(2)
178
-
179
- formatter = EdgesRecordFormatter.new
180
- #formatter = PageSplitTestFormatter.new
181
- space = Innodb::Space.new(file)
182
- space.record_formatter = formatter
183
- space.page(page_number).dump
184
- #space.each_page { |page_number, page| puts "%6i%20s" % [page_number, page.type] }
185
- #dump_space(space)
186
- #dump_index_level(Innodb::Index.new(space, page_number), 1)
187
- #recurse_index(Innodb::Index.new(space, page_number))
188
- #digraph_index(Innodb::Index.new(space, page_number))
189
- #Innodb::Index.new(space, page_number).each_record { |record| puts "(#{record[:key].join(", ")}) -> (#{record[:row].join(", ")})" }