innodb_ruby 0.8.1 → 0.8.5

Sign up to get free protection for your applications and to get access to all the features.
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