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 +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
|
|