innodb_ruby 0.8.1 → 0.8.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/AUTHORS.md ADDED
@@ -0,0 +1,12 @@
1
+ # Primary Authors #
2
+
3
+ The primary authors of `innodb_ruby` have been:
4
+
5
+ * Jeremy Cole \<jeremy@jcole.us\>
6
+ * Davi Arnaut \<davi.arnaut@gmail.com\>
7
+
8
+ # Contributors #
9
+
10
+ Special thanks to the following contributors who have taken an interest and contributed their fixes:
11
+
12
+ * Andrew Gaul \<gaul@maginatics.com\>
data/LICENSE ADDED
@@ -0,0 +1,29 @@
1
+ This software is licensed under the Revised (3-clause) BSD license as follows:
2
+
3
+ Copyright (c) 2013, Twitter, Inc.
4
+ Copyright (c) 2013, Jeremy Cole <jeremy@jcole.us>
5
+ Copyright (c) 2013, Davi Arnaut <davi.arnaut@gmail.com>
6
+
7
+ All rights reserved.
8
+
9
+ Redistribution and use in source and binary forms, with or without
10
+ modification, are permitted provided that the following conditions are met:
11
+ * Redistributions of source code must retain the above copyright
12
+ notice, this list of conditions and the following disclaimer.
13
+ * Redistributions in binary form must reproduce the above copyright
14
+ notice, this list of conditions and the following disclaimer in the
15
+ documentation and/or other materials provided with the distribution.
16
+ * Neither the name of the <organization> nor the
17
+ names of its contributors may be used to endorse or promote products
18
+ derived from this software without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
24
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/bin/innodb_log CHANGED
@@ -1,12 +1,62 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ require "getoptlong"
4
+ require "ostruct"
5
+ require "set"
3
6
  require "innodb"
4
7
 
8
+ def usage(exit_code, message = nil)
9
+ print "Error: #{message}\n" unless message.nil?
10
+
11
+ print <<'END_OF_USAGE'
12
+
13
+ Usage: innodb_log [-d] [-s] <file> [block-number]
14
+
15
+ --help, -?
16
+ Print this usage text.
17
+
18
+ --dump-blocks, -d
19
+ Dump block header, trailer, and record.
20
+
21
+ --space-id, -s
22
+ Print only given space id (may provide multiple times).
23
+
24
+ END_OF_USAGE
25
+
26
+ exit exit_code
27
+ end
28
+
29
+ @options = OpenStruct.new
30
+ @options.dump = false
31
+ @options.space_ids = Set.new
32
+
33
+ getopt_options = [
34
+ [ "--help", "-?", GetoptLong::NO_ARGUMENT ],
35
+ [ "--dump-blocks", "-d", GetoptLong::NO_ARGUMENT ],
36
+ [ "--space-id", "-s", GetoptLong::REQUIRED_ARGUMENT ],
37
+ ]
38
+
39
+ getopt = GetoptLong.new(*getopt_options)
40
+
41
+ getopt.each do |opt, arg|
42
+ case opt
43
+ when "--help"
44
+ usage 0
45
+ when "--dump-blocks"
46
+ @options.dump = true
47
+ when "--space-id"
48
+ @options.space_ids << Integer(arg)
49
+ end
50
+ end
51
+
5
52
  filename, block_number = ARGV.shift(2)
53
+ if filename.nil?
54
+ usage 1
55
+ end
6
56
 
7
57
  log = Innodb::Log.new(filename)
8
58
 
9
- puts "%-10s%-20s%-10s%-10s" % [
59
+ puts "%-10s%-30s%-10s%-10s" % [
10
60
  "block",
11
61
  "type",
12
62
  "space",
@@ -14,12 +64,17 @@ puts "%-10s%-20s%-10s%-10s" % [
14
64
  ]
15
65
  log.each_block do |block_number, block|
16
66
  if block.record
17
- puts "%-10i%-20s%-10i%-10i" % [
18
- block_number,
19
- block.record[:type],
20
- block.record[:space],
21
- block.record[:page_number],
22
- ]
23
- #block.dump
67
+ space_id = block.record[:space]
68
+ if @options.space_ids.empty? or @options.space_ids.include?(space_id)
69
+ puts "%-10i%-30s%-10i%-10i" % [
70
+ block_number,
71
+ block.record[:type],
72
+ space_id,
73
+ block.record[:page_number],
74
+ ]
75
+ if @options.dump
76
+ block.dump
77
+ end
78
+ end
24
79
  end
25
- end
80
+ end
data/bin/innodb_space CHANGED
@@ -386,16 +386,16 @@ def page_directory_summary(page)
386
386
 
387
387
  page.directory.each_with_index do |offset, slot|
388
388
  record = page.record(offset)
389
- key = if [:conventional, :node_pointer].include? record[:header][:type]
390
- if record[:key]
391
- "(%s)" % record[:key].map { |r| "%s=%s" % [r[:name], r[:value]] }.join(", ")
389
+ key = if [:conventional, :node_pointer].include? record.header[:type]
390
+ if record.key
391
+ "(%s)" % record.key.map { |r| "%s=%s" % [r[:name], r[:value]] }.join(", ")
392
392
  end
393
393
  end
394
394
  puts "%-8i%-8i%-14s%-8i%s" % [
395
395
  slot,
396
396
  offset,
397
- record[:header][:type],
398
- record[:header][:n_owned],
397
+ record.header[:type],
398
+ record.header[:n_owned],
399
399
  key,
400
400
  ]
401
401
  end
@@ -443,8 +443,8 @@ def index_recurse(index)
443
443
  page.each_record do |record|
444
444
  puts "%sRECORD: (%s) -> (%s)" % [
445
445
  " " * (depth+1),
446
- record[:key].map { |r| "%s=%s" % [r[:name], r[:value]] }.join(", "),
447
- record[:row].map { |r| "%s=%s" % [r[:name], r[:value]] }.join(", "),
446
+ record.key.map { |r| "%s=%s" % [r[:name], r[:value]] }.join(", "),
447
+ record.row.map { |r| "%s=%s" % [r[:name], r[:value]] }.join(", "),
448
448
  ]
449
449
  end
450
450
  end
@@ -459,6 +459,26 @@ def index_recurse(index)
459
459
  )
460
460
  end
461
461
 
462
+ def index_record_offsets(index)
463
+ puts "%-20s%-20s" % [
464
+ "page_offset",
465
+ "record_offset",
466
+ ]
467
+ index.recurse(
468
+ lambda do |page, depth|
469
+ if page.level == 0
470
+ page.each_record do |record|
471
+ puts "%-20i%-20i" % [
472
+ page.offset,
473
+ record.offset,
474
+ ]
475
+ end
476
+ end
477
+ end,
478
+ lambda { |*x| }
479
+ )
480
+ end
481
+
462
482
  def index_digraph(index)
463
483
  puts "digraph btree {"
464
484
  puts " rankdir = LR;"
@@ -513,7 +533,7 @@ def index_level_summary(index, levels)
513
533
  page.record_space,
514
534
  page.free_space,
515
535
  page.records,
516
- page.first_record[:key].map { |r| r[:value] }.join("|"),
536
+ page.first_record.key.map { |r| r[:value] }.join("|"),
517
537
  ]
518
538
  end
519
539
  end
@@ -543,7 +563,7 @@ Usage: innodb_space -f <file> [-p <page>] [-l <level>] <mode> [<mode>, ...]
543
563
  Operate on the level <level>; may be specified more than once.
544
564
 
545
565
  --list, -L <list>
546
- Operate on the list <list>; may be specified more than once.
566
+ Operate on the list <list>; may be specified more than once.
547
567
 
548
568
  --require, -r <file>
549
569
  Use Ruby's "require" to load the file <file>. This is useful for loading
@@ -576,9 +596,9 @@ The following modes are supported:
576
596
  provide an overall view of the space and allocations within it. A starting
577
597
  page number can be provided with the --page/-p argument.
578
598
 
579
- space-page-type-summary
580
- Summarize all pages by type. A starting page number can be provided with
581
- the --page/-p argument.
599
+ space-page-type-summary
600
+ Summarize all pages by type. A starting page number can be provided with
601
+ the --page/-p argument.
582
602
 
583
603
  space-indexes
584
604
  Summarize all indexes (actually each segment of the indexes) to show
@@ -615,6 +635,10 @@ The following modes are supported:
615
635
  pages. A record describer must be provided with the --describer/-d argument
616
636
  to recurse indexes (in order to parse node pages).
617
637
 
638
+ index-record-offsets
639
+ Recurse an index as index-recurse does, but print the offsets of each
640
+ record within the page.
641
+
618
642
  index-digraph
619
643
  Recurse an index as index-recurse does, but print a dot-compatible digraph
620
644
  instead of a human-readable summary.
@@ -649,23 +673,29 @@ Signal.trap("INT") { exit }
649
673
  Signal.trap("PIPE") { exit }
650
674
 
651
675
  @options = OpenStruct.new
652
- @options.file = nil
653
- @options.page_size = nil
654
- @options.pages = []
655
- @options.levels = []
656
- @options.lists = []
657
- @options.describer = nil
676
+ @options.system_space_file = nil
677
+ @options.space_file = nil
678
+ @options.table_name = nil
679
+ @options.index_name = nil
680
+ @options.pages = []
681
+ @options.levels = []
682
+ @options.lists = []
683
+ @options.page_size = nil
684
+ @options.describer = nil
658
685
 
659
686
  getopt_options = [
660
- [ "--help", "-?", GetoptLong::NO_ARGUMENT ],
661
- [ "--trace", "-t", GetoptLong::NO_ARGUMENT ],
662
- [ "--file", "-f", GetoptLong::REQUIRED_ARGUMENT ],
663
- [ "--page-size", "-P", GetoptLong::REQUIRED_ARGUMENT ],
664
- [ "--page", "-p", GetoptLong::REQUIRED_ARGUMENT ],
665
- [ "--level", "-l", GetoptLong::REQUIRED_ARGUMENT ],
666
- [ "--list", "-L", GetoptLong::REQUIRED_ARGUMENT ],
667
- [ "--require", "-r", GetoptLong::REQUIRED_ARGUMENT ],
668
- [ "--describer", "-d", GetoptLong::REQUIRED_ARGUMENT ],
687
+ [ "--help", "-?", GetoptLong::NO_ARGUMENT ],
688
+ [ "--trace", "-t", GetoptLong::NO_ARGUMENT ],
689
+ [ "--system-space-file", "-s", GetoptLong::REQUIRED_ARGUMENT ],
690
+ [ "--space-file", "-f", GetoptLong::REQUIRED_ARGUMENT ],
691
+ [ "--table-name", "-T", GetoptLong::REQUIRED_ARGUMENT ],
692
+ [ "--index-name", "-I", GetoptLong::REQUIRED_ARGUMENT ],
693
+ [ "--page", "-p", GetoptLong::REQUIRED_ARGUMENT ],
694
+ [ "--level", "-l", GetoptLong::REQUIRED_ARGUMENT ],
695
+ [ "--list", "-L", GetoptLong::REQUIRED_ARGUMENT ],
696
+ [ "--require", "-r", GetoptLong::REQUIRED_ARGUMENT ],
697
+ [ "--page-size", "-P", GetoptLong::REQUIRED_ARGUMENT ],
698
+ [ "--describer", "-d", GetoptLong::REQUIRED_ARGUMENT ],
669
699
  ]
670
700
 
671
701
  getopt = GetoptLong.new(*getopt_options)
@@ -678,13 +708,14 @@ getopt.each do |opt, arg|
678
708
  Innodb::Cursor.trace!
679
709
  when "--mode"
680
710
  @options.mode = arg
681
- when "--file"
682
- @options.file = arg
683
- when "--page-size"
684
- unless [1, 2, 4, 8, 16].include?(arg.to_i)
685
- usage 1, "Page size #{arg} is not understood"
686
- end
687
- @options.page_size = arg.to_i * 1024
711
+ when "--system-space-file"
712
+ @options.system_space_file = arg
713
+ when "--space-file"
714
+ @options.space_file = arg
715
+ when "--table-name"
716
+ @options.table_name = arg
717
+ when "--index-name"
718
+ @options.index_name = arg
688
719
  when "--page"
689
720
  @options.pages << arg.to_i
690
721
  when "--level"
@@ -692,17 +723,27 @@ getopt.each do |opt, arg|
692
723
  when "--list"
693
724
  @options.lists << arg.to_sym
694
725
  when "--require"
695
- require arg
726
+ require File.expand_path(arg)
727
+ when "--page-size"
728
+ unless [1, 2, 4, 8, 16].include?(arg.to_i)
729
+ usage 1, "Page size #{arg} is not understood"
730
+ end
731
+ @options.page_size = arg.to_i * 1024
696
732
  when "--describer"
697
733
  @options.describer = arg
698
734
  end
699
735
  end
700
736
 
701
- unless @options.file
702
- usage 1, "File must be provided with -f argument"
737
+ system_space = nil
738
+ if @options.system_space_file
739
+ system_space = Innodb::Space.new(@options.system_space_file)
740
+ end
741
+
742
+ unless @options.space_file
743
+ usage 1, "Space file must be provided with -f argument"
703
744
  end
704
745
 
705
- space = Innodb::Space.new(@options.file, @options.page_size)
746
+ space = Innodb::Space.new(@options.space_file, @options.page_size)
706
747
 
707
748
  if @options.describer
708
749
  describer = eval(@options.describer)
@@ -750,7 +791,7 @@ ARGV.each do |mode|
750
791
  when "space-index-pages-summary"
751
792
  space_index_pages_summary(space, @options.pages.first || 0)
752
793
  when "space-index-pages-free-plot"
753
- name = File.basename(@options.file).sub(".ibd", "")
794
+ name = File.basename(@options.space_file).sub(".ibd", "")
754
795
  space_index_pages_free_plot(space, name, @options.pages.first || 0)
755
796
  when "space-page-type-regions"
756
797
  space_page_type_regions(space, @options.pages.first || 0)
@@ -778,7 +819,7 @@ ARGV.each do |mode|
778
819
  unless space.record_describer
779
820
  usage 1, "Record describer necessary for index recursion"
780
821
  end
781
-
822
+
782
823
  if @options.pages.empty?
783
824
  usage 1, "Page number of index root must be provided with --page/-p"
784
825
  end
@@ -786,11 +827,23 @@ ARGV.each do |mode|
786
827
  @options.pages.each do |page|
787
828
  index_recurse(space.index(page))
788
829
  end
830
+ when "index-record-offsets"
831
+ unless space.record_describer
832
+ usage 1, "Record describer necessary for index recursion"
833
+ end
834
+
835
+ if @options.pages.empty?
836
+ usage 1, "Page number of index root must be provided with --page/-p"
837
+ end
838
+
839
+ @options.pages.each do |page|
840
+ index_record_offsets(space.index(page))
841
+ end
789
842
  when "index-digraph"
790
843
  unless space.record_describer
791
844
  usage 1, "Record describer necessary for index recursion"
792
845
  end
793
-
846
+
794
847
  if @options.pages.empty?
795
848
  usage 1, "Page number of index root must be provided with --page/-p"
796
849
  end
@@ -802,7 +855,7 @@ ARGV.each do |mode|
802
855
  unless space.record_describer
803
856
  usage 1, "Record describer necessary for index recursion"
804
857
  end
805
-
858
+
806
859
  if @options.pages.empty?
807
860
  usage 1, "Page number of index root must be provided with --page/-p"
808
861
  end
@@ -1,4 +1,5 @@
1
1
  # -*- encoding : utf-8 -*-
2
+
2
3
  class Innodb::Checksum
3
4
  MAX = 0xFFFFFFFF.freeze
4
5
  MASK1 = 1463735687.freeze
data/lib/innodb/cursor.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # -*- encoding : utf-8 -*-
2
+
2
3
  require "bindata"
3
4
 
4
5
  # A cursor to walk through InnoDB data structures to read fields.
@@ -270,78 +271,22 @@ class Innodb::Cursor
270
271
 
271
272
  # Read an InnoDB-compressed unsigned 32-bit integer.
272
273
  def get_ic_uint32
273
- flag = peek { get_uint8 }
274
+ flag = peek { name("ic_uint32") { get_uint8 } }
274
275
 
275
276
  case
276
277
  when flag < 0x80
277
- get_uint8
278
+ name("uint8") { get_uint8 }
278
279
  when flag < 0xc0
279
- get_uint16 & 0x7fff
280
+ name("uint16") { get_uint16 } & 0x7fff
280
281
  when flag < 0xe0
281
- get_uint24 & 0x3fffff
282
+ name("uint24") { get_uint24 } & 0x3fffff
282
283
  when flag < 0xf0
283
- get_uint32 & 0x1fffffff
284
+ name("uint32") { get_uint32 } & 0x1fffffff
284
285
  when flag == 0xf0
285
286
  adjust(+1) # Skip the flag.
286
- get_uint32
287
+ name("uint32+1") { get_uint32 }
287
288
  else
288
- raise "Invalid flag #{flag.to_s(16)} seen"
289
- end
290
- end
291
-
292
- # Read an InnoDB-munged signed 8-bit integer.
293
- def get_i_sint8
294
- data = read_and_advance(1)
295
- BinData::Int8.read(data) ^ (-1 << 7)
296
- end
297
-
298
- # Read an InnoDB-munged signed 16-bit integer.
299
- def get_i_sint16
300
- data = read_and_advance(2)
301
- BinData::Int16be.read(data) ^ (-1 << 15)
302
- end
303
-
304
- # Read an InnoDB-munged signed 24-bit integer.
305
- def get_i_sint24
306
- data = read_and_advance(3)
307
- BinData::Int24be.read(data) ^ (-1 << 23)
308
- end
309
-
310
- # Read an InnoDB-munged signed 32-bit integer.
311
- def get_i_sint32
312
- data = read_and_advance(4)
313
- BinData::Int32be.read(data) ^ (-1 << 31)
314
- end
315
-
316
- # Read an InnoDB-munged signed 48-bit integer.
317
- def get_i_sint48
318
- data = read_and_advance(6)
319
- BinData::Int48be.read(data) ^ (-1 << 47)
320
- end
321
-
322
- # Read an InnoDB-munged signed 64-bit integer.
323
- def get_i_sint64
324
- data = read_and_advance(8)
325
- BinData::Int64be.read(data) ^ (-1 << 63)
326
- end
327
-
328
- # Read an InnoDB-munged signed integer given its size in bytes.
329
- def get_i_sint_by_size(size)
330
- case size
331
- when 1
332
- get_i_sint8
333
- when 2
334
- get_i_sint16
335
- when 3
336
- get_i_sint24
337
- when 4
338
- get_i_sint32
339
- when 6
340
- get_i_sint48
341
- when 8
342
- get_i_sint64
343
- else
344
- raise "Not implemented"
289
+ raise "Invalid flag #{flag.to_s} seen"
345
290
  end
346
291
  end
347
292
 
@@ -1,3 +1,5 @@
1
+ # -*- encoding : utf-8 -*-
2
+
1
3
  class Innodb::DataDictionary
2
4
  # A record describer for SYS_TABLES clustered records.
3
5
  class SYS_TABLES_PRIMARY < Innodb::RecordDescriber