innodb_ruby 0.7.5 → 0.7.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,27 +5,46 @@ require "ostruct"
5
5
  require "pp"
6
6
  require "innodb"
7
7
 
8
- def space_summary(space, start_page)
9
- puts "%-12s%-20s%-12s%-12s%-20s" % [
10
- "page",
11
- "type",
12
- "prev",
13
- "next",
14
- "lsn",
8
+ def print_lists(lists)
9
+ puts "%-20s%-12s%-12s%-12s%-12s%-12s" % [
10
+ "name",
11
+ "length",
12
+ "f_page",
13
+ "f_offset",
14
+ "l_page",
15
+ "l_offset",
15
16
  ]
16
17
 
17
- space.each_page(start_page) do |page_number, page|
18
- puts "%-12i%-20s%-12i%-12i%-20i" % [
19
- page_number,
20
- page.type,
21
- page.prev || 0,
22
- page.next || 0,
23
- page.lsn || 0,
18
+ lists.each do |name, list|
19
+ puts "%-20s%-12i%-12i%-12i%-12i%-12i" % [
20
+ name,
21
+ list.base[:length],
22
+ list.base[:first] && list.base[:first][:page] || 0,
23
+ list.base[:first] && list.base[:first][:offset] || 0,
24
+ list.base[:last] && list.base[:last][:page] || 0,
25
+ list.base[:last] && list.base[:last][:offset] || 0,
24
26
  ]
25
27
  end
26
28
  end
27
29
 
28
- def space_index_pages_summary(space, start_page)
30
+ def print_xdes_list(list)
31
+ puts "%-12s%-64s" % [
32
+ "start_page",
33
+ "page_used_bitmap"
34
+ ]
35
+
36
+ list.each do |entry|
37
+ puts "%-12i%-64s" % [
38
+ entry.xdes[:start_page],
39
+ entry.each_page_status.inject("") { |bitmap, page_status|
40
+ bitmap += page_status[:free] ? "." : "#"
41
+ bitmap
42
+ },
43
+ ]
44
+ end
45
+ end
46
+
47
+ def print_index_page_summary(pages)
29
48
  puts "%-12s%-8s%-8s%-8s%-8s%-8s" % [
30
49
  "page",
31
50
  "index",
@@ -35,7 +54,7 @@ def space_index_pages_summary(space, start_page)
35
54
  "records",
36
55
  ]
37
56
 
38
- space.each_page(start_page) do |page_number, page|
57
+ pages.each do |page_number, page|
39
58
  case page.type
40
59
  when :INDEX
41
60
  puts "%-12i%-8i%-8i%-8i%-8i%-8i" % [
@@ -52,6 +71,30 @@ def space_index_pages_summary(space, start_page)
52
71
  end
53
72
  end
54
73
 
74
+ def space_summary(space, start_page)
75
+ puts "%-12s%-20s%-12s%-12s%-20s" % [
76
+ "page",
77
+ "type",
78
+ "prev",
79
+ "next",
80
+ "lsn",
81
+ ]
82
+
83
+ space.each_page(start_page) do |page_number, page|
84
+ puts "%-12i%-20s%-12i%-12i%-20i" % [
85
+ page_number,
86
+ page.type,
87
+ page.prev || 0,
88
+ page.next || 0,
89
+ page.lsn || 0,
90
+ ]
91
+ end
92
+ end
93
+
94
+ def space_index_pages_summary(space, start_page)
95
+ print_index_page_summary(space.each_page(start_page))
96
+ end
97
+
55
98
  def space_page_type_regions(space, start_page)
56
99
  puts "%-12s%-12s%-12s%-20s" % [
57
100
  "start",
@@ -71,25 +114,28 @@ def space_page_type_regions(space, start_page)
71
114
  end
72
115
 
73
116
  def space_lists(space)
117
+ print_lists(space.page(0).each_list)
118
+ end
119
+
120
+ def space_list_iterate(space, list_name)
74
121
  fsp = space.page(0).fsp_header
75
- puts "%-20s%-12s%-12s%-12s%-12s%-12s" % [
76
- "name",
77
- "length",
78
- "f_page",
79
- "f_offset",
80
- "l_page",
81
- "l_offset",
82
- ]
83
- fsp.each do |key, list|
84
- next unless list.is_a?(Innodb::List)
85
- puts "%-20s%-12i%-12i%-12i%-12i%-12i" % [
86
- key,
87
- list.base[:length],
88
- list.base[:first] && list.base[:first][:page],
89
- list.base[:first] && list.base[:first][:offset],
90
- list.base[:last] && list.base[:last][:page],
91
- list.base[:last] && list.base[:last][:offset],
122
+
123
+ unless fsp[list_name] && fsp[list_name].is_a?(Innodb::List)
124
+ raise "List '#{list_name}' doesn't exist"
125
+ end
126
+
127
+ case fsp[list_name]
128
+ when Innodb::List::Xdes
129
+ print_xdes_list(fsp[list_name])
130
+ when Innodb::List::Inode
131
+ puts "%-12s" % [
132
+ "page",
92
133
  ]
134
+ fsp[list_name].each do |page|
135
+ puts "%-12i" % [
136
+ page.offset,
137
+ ]
138
+ end
93
139
  end
94
140
  end
95
141
 
@@ -104,9 +150,7 @@ def space_indexes(space)
104
150
  ]
105
151
 
106
152
  space.each_index do |index|
107
- [:internal, :leaf].each do |fseg_name|
108
- fseg = index.root.fseg_header[fseg_name]
109
-
153
+ index.each_fseg do |fseg_name, fseg|
110
154
  fragments =
111
155
  fseg[:frag_array].inject(0) { |c, i| c += 1 if i; c }
112
156
 
@@ -121,70 +165,20 @@ def space_indexes(space)
121
165
  space.pages_per_extent * fseg[:not_full].base[:length] +
122
166
  space.pages_per_extent * fseg[:free].base[:length]
123
167
 
168
+ fill_factor = allocated > 0 ? 100.0 * (used.to_f / allocated.to_f) : 0.0
169
+
124
170
  puts "%-12i%-12i%-12s%-12i%-12i%-12s" % [
125
171
  index.id,
126
172
  index.root.offset,
127
173
  fseg_name,
128
174
  used,
129
175
  allocated,
130
- "%.2f%%" % [100.0 * (used.to_f / allocated.to_f)],
131
- ]
132
- end
133
- end
134
- end
135
-
136
- def print_xdes_list(list)
137
- puts "%-12s%-64s" % [
138
- "start_page",
139
- "bitmap"
140
- ]
141
- list.each do |entry|
142
- puts "%-12i%-64s" % [
143
- entry.xdes[:start_page],
144
- entry.each_page_status.inject("") { |bitmap, page_status|
145
- bitmap += page_status[:free] ? "." : "#"
146
- bitmap
147
- },
148
- ]
149
- end
150
- end
151
-
152
- def list_summary(space, list_name)
153
- fsp = space.page(0).fsp_header
154
-
155
- unless fsp[list_name] && fsp[list_name].is_a?(Innodb::List)
156
- raise "List '#{list_name}' doesn't exist"
157
- end
158
-
159
- case fsp[list_name]
160
- when Innodb::List::Xdes
161
- print_xdes_list(fsp[list_name])
162
- when Innodb::List::Inode
163
- puts "%-12s" % [
164
- "page",
165
- ]
166
- fsp[list_name].each do |page|
167
- puts "%-12i" % [
168
- page.offset,
176
+ "%.2f%%" % fill_factor,
169
177
  ]
170
178
  end
171
179
  end
172
180
  end
173
181
 
174
- def index_fseg_summary(index, fseg_name, list_name)
175
- fseg_header = index.root.fseg_header
176
- unless fseg_header[fseg_name]
177
- raise "File segment '#{fseg_name}' doesn't exist"
178
- end
179
-
180
- fseg = fseg_header[fseg_name]
181
- unless fseg[list_name] && fseg[list_name].is_a?(Innodb::List)
182
- raise "List '#{list_name}' doesn't exist"
183
- end
184
-
185
- print_xdes_list(fseg[list_name])
186
- end
187
-
188
182
  def space_index_pages_free_plot(space, image, start_page)
189
183
  unless require "gnuplot"
190
184
  raise "Couldn't load gnuplot. Is it installed?"
@@ -231,6 +225,35 @@ def space_index_pages_free_plot(space, image, start_page)
231
225
  end
232
226
  end
233
227
 
228
+ def index_fseg_lists(index, fseg_name)
229
+ unless index.fseg(fseg_name)
230
+ raise "File segment '#{fseg_name}' doesn't exist"
231
+ end
232
+
233
+ print_lists(index.each_fseg_list(index.fseg(fseg_name)))
234
+ end
235
+
236
+ def index_fseg_list_iterate(index, fseg_name, list_name)
237
+ unless index.fseg(fseg_name)
238
+ raise "File segment '#{fseg_name}' doesn't exist"
239
+ end
240
+
241
+ fseg = index.fseg(fseg_name)
242
+ unless fseg[list_name] && fseg[list_name].is_a?(Innodb::List)
243
+ raise "List '#{list_name}' doesn't exist"
244
+ end
245
+
246
+ print_xdes_list(fseg[list_name])
247
+ end
248
+
249
+ def index_fseg_frag_pages(index, fseg_name)
250
+ unless index.fseg(fseg_name)
251
+ raise "File segment '#{fseg_name}' doesn't exist"
252
+ end
253
+
254
+ print_index_page_summary(index.each_fseg_frag_page(index.fseg(fseg_name)))
255
+ end
256
+
234
257
  def index_recurse(index)
235
258
  index.recurse(
236
259
  lambda do |page, depth|
@@ -381,15 +404,15 @@ The following modes are supported:
381
404
  provide an overall view of the space and allocations within it. A starting
382
405
  page number can be provided with the --page/-p argument.
383
406
 
384
- space-lists
385
- Print the names of all lists in a space.
386
-
387
407
  space-indexes
388
408
  Summarize all indexes (actually each segment of the indexes) to show
389
409
  the number of pages used and allocated, and the segment fill factor.
390
410
 
391
- list-summary
392
- Summarize the contents of a list.
411
+ space-lists
412
+ Print a summary of all lists in a space.
413
+
414
+ space-list-iterate
415
+ Iterate through the contents of a space list.
393
416
 
394
417
  index-recurse
395
418
  Recurse an index, starting at the root (which must be provided in the first
@@ -405,13 +428,23 @@ The following modes are supported:
405
428
  Print a summary of all pages at a given level (provided with the --level/-l
406
429
  argument) in an index.
407
430
 
408
- index-fseg-internal-summary
409
- index-fseg-leaf-summary
410
- Summarize the file segment (whose name is provided in the first --list/-L
431
+ index-fseg-internal-lists
432
+ index-fseg-leaf-lists
433
+ Print a summary of all lists in an index file segment. Index root page must
434
+ be provided with --page/-p.
435
+
436
+ index-fseg-internal-list-iterate
437
+ index-fseg-leaf-list-iterate
438
+ Iterate the file segment list (whose name is provided in the first --list/-L
411
439
  argument) for internal or leaf pages for a given index (whose root page
412
440
  is provided in the first --page/-p argument). The lists used for each
413
441
  index are "full", "not_full", and "free".
414
442
 
443
+ index-fseg-internal-frag-pages
444
+ index-fseg-leaf-frag-pages
445
+ Print a summary of all fragment pages in an index file segment. Index root
446
+ page must be provided with --page/-p.
447
+
415
448
  END_OF_USAGE
416
449
 
417
450
  exit exit_code
@@ -482,7 +515,7 @@ ARGV.each do |mode|
482
515
  case mode
483
516
  when "page-dump"
484
517
  if @options.pages.empty?
485
- usage 1, "Page numbers to dump must be provided"
518
+ usage 1, "Page numbers to dump must be provided with --page/-p"
486
519
  end
487
520
 
488
521
  @options.pages.each do |page|
@@ -499,19 +532,23 @@ ARGV.each do |mode|
499
532
  space_page_type_regions(space, @options.pages.first || 0)
500
533
  when "space-lists"
501
534
  space_lists(space)
502
- when "space-indexes"
503
- space_indexes(space)
504
- when "list-summary"
535
+ when "space-list-iterate"
536
+ if @options.lists.empty?
537
+ usage 1, "A list name must be provided with --list/-L"
538
+ end
539
+
505
540
  @options.lists.each do |list|
506
- list_summary(space, list)
541
+ space_list_iterate(space, list)
507
542
  end
543
+ when "space-indexes"
544
+ space_indexes(space)
508
545
  when "index-recurse"
509
546
  unless space.record_describer
510
547
  usage 1, "Record describer necessary for index recursion"
511
548
  end
512
549
 
513
550
  if @options.pages.empty?
514
- usage 1, "Page number of index root must be provided"
551
+ usage 1, "Page number of index root must be provided with --page/-p"
515
552
  end
516
553
 
517
554
  @options.pages.each do |page|
@@ -523,7 +560,7 @@ ARGV.each do |mode|
523
560
  end
524
561
 
525
562
  if @options.pages.empty?
526
- usage 1, "Page number of index root must be provided"
563
+ usage 1, "Page number of index root must be provided with --page/-p"
527
564
  end
528
565
 
529
566
  @options.pages.each do |page|
@@ -535,18 +572,58 @@ ARGV.each do |mode|
535
572
  end
536
573
 
537
574
  if @options.pages.empty?
538
- usage 1, "Page number of index root must be provided"
575
+ usage 1, "Page number of index root must be provided with --page/-p"
539
576
  end
540
577
 
541
578
  index_level_summary(space.index(@options.pages.first), @options.levels)
542
- when "index-fseg-leaf-summary"
579
+ when "index-fseg-leaf-lists"
580
+ if @options.pages.empty?
581
+ usage 1, "Page number of index root must be provided with --page/-p"
582
+ end
583
+
584
+ index_fseg_lists(space.index(@options.pages.first), :leaf)
585
+ when "index-fseg-internal-lists"
586
+ if @options.pages.empty?
587
+ usage 1, "Page number of index root must be provided with --page/-p"
588
+ end
589
+
590
+ index_fseg_lists(space.index(@options.pages.first), :internal)
591
+ when "index-fseg-leaf-list-iterate"
592
+ if @options.pages.empty?
593
+ usage 1, "Page number of index root must be provided with --page/-p"
594
+ end
595
+
596
+ if @options.lists.empty?
597
+ usage 1, "A list name must be provided with --list/-L"
598
+ end
599
+
543
600
  @options.lists.each do |list|
544
- index_fseg_summary(space.index(@options.pages.first), :leaf, list)
601
+ index_fseg_list_iterate(space.index(@options.pages.first), :leaf, list)
602
+ end
603
+ when "index-fseg-internal-list-iterate"
604
+ if @options.pages.empty?
605
+ usage 1, "Page number of index root must be provided with --page/-p"
545
606
  end
546
- when "index-fseg-internal-summary"
607
+
608
+ if @options.lists.empty?
609
+ usage 1, "A list name must be provided with --list/-L"
610
+ end
611
+
547
612
  @options.lists.each do |list|
548
- index_fseg_summary(space.index(@options.pages.first), :internal, list)
613
+ index_fseg_list_iterate(space.index(@options.pages.first), :internal, list)
549
614
  end
615
+ when "index-fseg-leaf-frag-pages"
616
+ if @options.pages.empty?
617
+ usage 1, "Page number of index root must be provided with --page/-p"
618
+ end
619
+
620
+ index_fseg_frag_pages(space.index(@options.pages.first), :leaf)
621
+ when "index-fseg-internal-frag-pages"
622
+ if @options.pages.empty?
623
+ usage 1, "Page number of index root must be provided with --page/-p"
624
+ end
625
+
626
+ index_fseg_frag_pages(space.index(@options.pages.first), :internal)
550
627
  else
551
628
  usage 1, "Unknown mode: #{mode}"
552
629
  end
@@ -1,6 +1,8 @@
1
1
  # A set of classes for parsing and working with InnoDB data files.
2
2
  module Innodb; end
3
3
 
4
+ require "enumerator"
5
+
4
6
  require "innodb/version"
5
7
  require "innodb/page"
6
8
  require "innodb/page/fsp_hdr_xdes"
@@ -82,10 +82,48 @@ class Innodb::Index
82
82
  page if page.level == level
83
83
  end
84
84
 
85
+ # Return the file segment with the given name from the fseg header.
86
+ def fseg(name)
87
+ @root.fseg_header[name]
88
+ end
89
+
90
+ # Iterate through all file segments in the index.
91
+ def each_fseg
92
+ unless block_given?
93
+ return enum_for(:each_fseg)
94
+ end
95
+
96
+ [:internal, :leaf].each do |fseg_name|
97
+ yield fseg_name, fseg(fseg_name)
98
+ end
99
+ end
100
+
101
+ # Iterate through all lists in a given fseg.
102
+ def each_fseg_list(fseg)
103
+ unless block_given?
104
+ return enum_for(:each_fseg_list, fseg)
105
+ end
106
+
107
+ [:full, :not_full, :free].each do |list_name|
108
+ yield list_name, fseg[list_name] if fseg[list_name].is_a?(Innodb::List)
109
+ end
110
+ end
111
+
112
+ # Iterate through all frag pages in a given fseg.
113
+ def each_fseg_frag_page(fseg)
114
+ unless block_given?
115
+ return enum_for(:each_fseg_frag_page, fseg)
116
+ end
117
+
118
+ fseg[:frag_array].each do |page_number|
119
+ yield page_number, @space.page(page_number) if page_number
120
+ end
121
+ end
122
+
85
123
  # Iterate through all pages at this level starting with the provided page.
86
124
  def each_page_from(page)
87
125
  unless block_given?
88
- return Enumerable::Enumerator.new(self, :each_page_from, page)
126
+ return enum_for(:each_page_from, page)
89
127
  end
90
128
 
91
129
  while page && page.type == :INDEX
@@ -98,7 +136,7 @@ class Innodb::Index
98
136
  # and following the next pointers in each page.
99
137
  def each_page_at_level(level)
100
138
  unless block_given?
101
- return Enumerable::Enumerator.new(self, :each_page_at_level, level)
139
+ return enum_for(:each_page_at_level, level)
102
140
  end
103
141
 
104
142
  each_page_from(first_page_at_level(level)) { |page| yield page }
@@ -107,7 +145,7 @@ class Innodb::Index
107
145
  # Iterate through all records on all leaf pages in ascending order.
108
146
  def each_record
109
147
  unless block_given?
110
- return Enumerable::Enumerator.new(self, :each_record)
148
+ return enum_for(:each_record)
111
149
  end
112
150
 
113
151
  each_page_at_level(0) do |page|
@@ -106,7 +106,7 @@ class Innodb::List
106
106
  # Iterate through all nodes in the list.
107
107
  def each
108
108
  unless block_given?
109
- return Enumerable::Enumerator.new(self)
109
+ return enum_for(:each)
110
110
  end
111
111
 
112
112
  c = cursor
@@ -58,13 +58,24 @@ class Innodb::Page::FspHdrXdes < Innodb::Page
58
58
  }
59
59
  end
60
60
 
61
+ # Iterate through all lists in the file space.
62
+ def each_list
63
+ unless block_given?
64
+ return enum_for(:each_list)
65
+ end
66
+
67
+ fsp_header.each do |key, value|
68
+ yield key, value if value.is_a?(Innodb::List)
69
+ end
70
+ end
71
+
61
72
  # Iterate through all XDES entries in order. This is useful for debugging,
62
73
  # but each of these entries is actually a node in some other list. The state
63
74
  # field in the XDES entry indicates which type of list it is present in,
64
75
  # although not necessarily which list (e.g. :fseg).
65
76
  def each_xdes
66
77
  unless block_given?
67
- return Enumerable::Enumerator.new(self, :each_xdes)
78
+ return enum_for(:each_xdes)
68
79
  end
69
80
 
70
81
  c = cursor(pos_xdes_array)
@@ -450,7 +450,7 @@ class Innodb::Page::Index < Innodb::Page
450
450
  # Iterate through all records.
451
451
  def each_record
452
452
  unless block_given?
453
- return Enumerable::Enumerator.new(self, :each_record)
453
+ return enum_for(:each_record)
454
454
  end
455
455
 
456
456
  c = record_cursor(infimum[:next])
@@ -469,7 +469,7 @@ class Innodb::Page::Index < Innodb::Page
469
469
  return nil if level == 0
470
470
 
471
471
  unless block_given?
472
- return Enumerable::Enumerator.new(self, :each_child_page)
472
+ return enum_for(:each_child_page)
473
473
  end
474
474
 
475
475
  each_record do |rec|
@@ -69,7 +69,7 @@ class Innodb::Space
69
69
  # files.
70
70
  def each_index
71
71
  unless block_given?
72
- return Enumerable::Enumerator.new(self, :each_index)
72
+ return enum_for(:each_index)
73
73
  end
74
74
 
75
75
  (3...@pages).each do |page_number|
@@ -86,7 +86,7 @@ class Innodb::Space
86
86
  # and an Innodb::Page object for each one.
87
87
  def each_page(start_page=0)
88
88
  unless block_given?
89
- return Enumerable::Enumerator.new(self, :each_page)
89
+ return enum_for(:each_page)
90
90
  end
91
91
 
92
92
  (start_page...@pages).each do |page_number|
@@ -99,7 +99,7 @@ class Innodb::Space
99
99
  # to achieve an overall view of the space.
100
100
  def each_page_type_region(start_page=0)
101
101
  unless block_given?
102
- return Enumerable::Enumerator.new(self, :each_page_type_region)
102
+ return enum_for(:each_page_type_region)
103
103
  end
104
104
 
105
105
  region = nil
@@ -1,3 +1,3 @@
1
1
  module Innodb
2
- VERSION = "0.7.5"
2
+ VERSION = "0.7.6"
3
3
  end
@@ -1,5 +1,3 @@
1
- require "enumerator"
2
-
3
1
  # An InnoDB "extent descriptor entry" or "+XDES+". These structures are used
4
2
  # in the +XDES+ entry array contained in +FSP_HDR+ and +XDES+ pages.
5
3
  #
@@ -85,10 +83,10 @@ class Innodb::Xdes
85
83
  # this bit is unused by InnoDB, and always set true).
86
84
  def each_page_status
87
85
  unless block_given?
88
- return Enumerable::Enumerator.new(self, :each_page_status)
86
+ return enum_for(:each_page_status)
89
87
  end
90
88
 
91
- bitmap = Enumerable::Enumerator.new(xdes[:bitmap], :each_byte)
89
+ bitmap = xdes[:bitmap].enum_for(:each_byte)
92
90
 
93
91
  bitmap.each_with_index do |byte, byte_index|
94
92
  (0..3).each_with_index do |page, page_index|
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: innodb_ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.5
4
+ version: 0.7.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-02 00:00:00.000000000 Z
12
+ date: 2013-01-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bindata
16
- requirement: &70358166884520 !ruby/object:Gem::Requirement
16
+ requirement: &70346481414780 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,7 +21,7 @@ dependencies:
21
21
  version: 1.4.5
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70358166884520
24
+ version_requirements: *70346481414780
25
25
  description: Library for parsing InnoDB data files in Ruby
26
26
  email: jeremy@jcole.us
27
27
  executables: