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 +12 -0
- data/LICENSE +29 -0
- data/bin/innodb_log +64 -9
- data/bin/innodb_space +95 -42
- data/lib/innodb/checksum.rb +1 -0
- data/lib/innodb/cursor.rb +8 -63
- data/lib/innodb/data_dictionary.rb +2 -0
- data/lib/innodb/data_type.rb +360 -0
- data/lib/innodb/field.rb +65 -10
- data/lib/innodb/fseg_entry.rb +2 -0
- data/lib/innodb/index.rb +5 -0
- data/lib/innodb/inode.rb +1 -0
- data/lib/innodb/list.rb +2 -0
- data/lib/innodb/log.rb +2 -0
- data/lib/innodb/log_block.rb +1 -0
- data/lib/innodb/log_group.rb +79 -0
- data/lib/innodb/page/fsp_hdr_xdes.rb +1 -0
- data/lib/innodb/page/index.rb +38 -42
- data/lib/innodb/page/index_compressed.rb +42 -0
- data/lib/innodb/page/inode.rb +1 -0
- data/lib/innodb/page/sys.rb +1 -0
- data/lib/innodb/page/sys_rseg_header.rb +1 -0
- data/lib/innodb/page/trx_sys.rb +1 -0
- data/lib/innodb/page.rb +1 -0
- data/lib/innodb/record.rb +49 -0
- data/lib/innodb/record_describer.rb +8 -0
- data/lib/innodb/space.rb +6 -0
- data/lib/innodb/system.rb +58 -0
- data/lib/innodb/undo_log.rb +1 -0
- data/lib/innodb/version.rb +2 -1
- data/lib/innodb/xdes.rb +1 -0
- data/lib/innodb.rb +4 -0
- metadata +13 -5
- data/lib/innodb/field_type.rb +0 -124
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%-
|
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
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
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
|
390
|
-
if record
|
391
|
-
"(%s)" % record
|
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
|
398
|
-
record
|
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
|
447
|
-
record
|
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
|
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
|
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
|
-
|
580
|
-
|
581
|
-
|
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.
|
653
|
-
@options.
|
654
|
-
@options.
|
655
|
-
@options.
|
656
|
-
@options.
|
657
|
-
@options.
|
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",
|
661
|
-
[ "--trace",
|
662
|
-
[ "--file",
|
663
|
-
[ "--
|
664
|
-
[ "--
|
665
|
-
[ "--
|
666
|
-
[ "--
|
667
|
-
[ "--
|
668
|
-
[ "--
|
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.
|
683
|
-
when "--
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
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
|
-
|
702
|
-
|
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.
|
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.
|
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
|
data/lib/innodb/checksum.rb
CHANGED
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
|
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
|
|