innodb_ruby 0.6.6 → 0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +12 -0
- data/bin/innodb_space +157 -1
- data/lib/innodb.rb +2 -0
- data/lib/innodb/cursor.rb +93 -31
- data/lib/innodb/field.rb +66 -0
- data/lib/innodb/fseg_entry.rb +13 -1
- data/lib/innodb/index.rb +106 -8
- data/lib/innodb/list.rb +109 -0
- data/lib/innodb/page.rb +26 -4
- data/lib/innodb/page/fsp_hdr_xdes.rb +35 -29
- data/lib/innodb/page/index.rb +103 -7
- data/lib/innodb/page/inode.rb +46 -9
- data/lib/innodb/page/trx_sys.rb +36 -10
- data/lib/innodb/space.rb +6 -1
- data/lib/innodb/version.rb +1 -1
- data/lib/innodb/xdes.rb +39 -0
- metadata +26 -8
- data/lib/innodb/free_list.rb +0 -27
data/lib/innodb/page/inode.rb
CHANGED
@@ -1,17 +1,30 @@
|
|
1
|
-
require "innodb/
|
1
|
+
require "innodb/list"
|
2
2
|
|
3
|
+
# A specialized class for handling INODE pages, which contain index FSEG (file
|
4
|
+
# segment) information. This allows all extents and individual pages assigned
|
5
|
+
# to each index to be found.
|
3
6
|
class Innodb::Page::Inode < Innodb::Page
|
7
|
+
# The number of "slots" (each representing one page) in the fragment array
|
8
|
+
# within each Inode entry.
|
4
9
|
FRAG_ARRAY_N_SLOTS = 32 # FSP_EXTENT_SIZE / 2
|
10
|
+
|
11
|
+
# The size (in bytes) of each slot in the fragment array.
|
5
12
|
FRAG_SLOT_SIZE = 4
|
6
13
|
|
14
|
+
# A magic number which helps determine if an Inode structure is in use
|
15
|
+
# and populated with valid data.
|
7
16
|
MAGIC_N_VALUE = 97937874
|
8
17
|
|
18
|
+
def pos_inode_list_entry
|
19
|
+
pos_fil_header + size_fil_header
|
20
|
+
end
|
21
|
+
|
9
22
|
def pos_inode_list
|
10
|
-
pos_fil_header + size_fil_header + Innodb::
|
23
|
+
pos_fil_header + size_fil_header + Innodb::List::NODE_SIZE
|
11
24
|
end
|
12
25
|
|
13
26
|
def size_inode
|
14
|
-
(16 + (3 * Innodb::
|
27
|
+
(16 + (3 * Innodb::List::BASE_NODE_SIZE) +
|
15
28
|
(FRAG_ARRAY_N_SLOTS * FRAG_SLOT_SIZE))
|
16
29
|
end
|
17
30
|
|
@@ -19,22 +32,42 @@ class Innodb::Page::Inode < Innodb::Page
|
|
19
32
|
(size - pos_inode_list - 10) / size_inode
|
20
33
|
end
|
21
34
|
|
22
|
-
def
|
23
|
-
size.times.map { |n| cursor.get_uint32 }
|
35
|
+
def page_number_array(size, cursor)
|
36
|
+
size.times.map { |n| Innodb::Page.maybe_undefined(cursor.get_uint32) }
|
37
|
+
end
|
38
|
+
|
39
|
+
def list_entry
|
40
|
+
c = cursor(pos_inode_list_entry)
|
41
|
+
Innodb::List.get_node(c)
|
42
|
+
end
|
43
|
+
|
44
|
+
def prev_address
|
45
|
+
list_entry[:prev]
|
46
|
+
end
|
47
|
+
|
48
|
+
def next_address
|
49
|
+
list_entry[:next]
|
24
50
|
end
|
25
51
|
|
26
52
|
def inode(cursor)
|
27
53
|
{
|
28
54
|
:fseg_id => cursor.get_uint64,
|
29
55
|
:not_full_n_used => cursor.get_uint32,
|
30
|
-
:free => Innodb::
|
31
|
-
|
32
|
-
:
|
56
|
+
:free => Innodb::List::Xdes.new(@space,
|
57
|
+
Innodb::List.get_base_node(cursor)),
|
58
|
+
:not_full => Innodb::List::Xdes.new(@space,
|
59
|
+
Innodb::List.get_base_node(cursor)),
|
60
|
+
:full => Innodb::List::Xdes.new(@space,
|
61
|
+
Innodb::List.get_base_node(cursor)),
|
33
62
|
:magic_n => cursor.get_uint32,
|
34
|
-
:frag_array =>
|
63
|
+
:frag_array => page_number_array(FRAG_ARRAY_N_SLOTS, cursor),
|
35
64
|
}
|
36
65
|
end
|
37
66
|
|
67
|
+
def inode_at(offset)
|
68
|
+
inode(cursor(offset))
|
69
|
+
end
|
70
|
+
|
38
71
|
def each_inode
|
39
72
|
inode_cursor = cursor(pos_inode_list)
|
40
73
|
inodes_per_page.times do
|
@@ -46,6 +79,10 @@ class Innodb::Page::Inode < Innodb::Page
|
|
46
79
|
def dump
|
47
80
|
super
|
48
81
|
|
82
|
+
puts "list entry:"
|
83
|
+
pp list_entry
|
84
|
+
puts
|
85
|
+
|
49
86
|
puts "inodes:"
|
50
87
|
each_inode do |i|
|
51
88
|
pp i
|
data/lib/innodb/page/trx_sys.rb
CHANGED
@@ -1,22 +1,41 @@
|
|
1
|
+
# A specialized class for TRX_SYS pages, which contain various information
|
2
|
+
# about the transaction system within InnoDB. Only one TRX_SYS page exists in
|
3
|
+
# any given InnoDB installation, and it is page 5 of the system tablespace
|
4
|
+
# (space 0), most commonly named "ibdata1".
|
5
|
+
#
|
6
|
+
# The basic structure of a TRX_SYS page is: FIL header, TRX_SYS header,
|
7
|
+
# empty space, master binary log information, empty space, local binary
|
8
|
+
# log information, empty space, doublewrite information (repeated twice),
|
9
|
+
# empty space, and FIL trailer.
|
1
10
|
class Innodb::Page::TrxSys < Innodb::Page
|
11
|
+
# The TRX_SYS header immediately follows the FIL header.
|
2
12
|
def pos_trx_sys_header
|
3
13
|
pos_fil_header + size_fil_header
|
4
14
|
end
|
5
15
|
|
6
|
-
|
7
|
-
|
8
|
-
end
|
9
|
-
|
16
|
+
# The master's binary log information is located 2000 bytes from the end of
|
17
|
+
# the page.
|
10
18
|
def pos_mysql_master_log_info
|
11
19
|
size - 2000
|
12
20
|
end
|
13
21
|
|
22
|
+
# The local binary log information is located 1000 bytes from the end of
|
23
|
+
# the page.
|
24
|
+
def pos_mysql_binary_log_info
|
25
|
+
size - 1000
|
26
|
+
end
|
27
|
+
|
28
|
+
# The doublewrite buffer information is located 200 bytes from the end of
|
29
|
+
# the page.
|
14
30
|
def pos_doublewrite_info
|
15
31
|
size - 200
|
16
32
|
end
|
17
33
|
|
34
|
+
# A magic number present in each MySQL binary log information structure,
|
35
|
+
# which helps identify whether the structure is populated or not.
|
18
36
|
MYSQL_LOG_MAGIC_N = 873422344
|
19
37
|
|
38
|
+
# Read a MySQL binary log information structure from a given position.
|
20
39
|
def mysql_log_info(offset)
|
21
40
|
c = cursor(offset)
|
22
41
|
if c.get_uint32 == MYSQL_LOG_MAGIC_N
|
@@ -27,8 +46,11 @@ class Innodb::Page::TrxSys < Innodb::Page
|
|
27
46
|
end
|
28
47
|
end
|
29
48
|
|
49
|
+
# A magic number present in each doublewrite buffer information structure,
|
50
|
+
# which helps identify whether the structure is populated or not.
|
30
51
|
DOUBLEWRITE_MAGIC_N = 536853855
|
31
52
|
|
53
|
+
# Read a single doublewrite buffer information structure from a given cursor.
|
32
54
|
def doublewrite_page_info(cursor)
|
33
55
|
{
|
34
56
|
:magic_n => cursor.get_uint32,
|
@@ -39,12 +61,15 @@ class Innodb::Page::TrxSys < Innodb::Page
|
|
39
61
|
}
|
40
62
|
end
|
41
63
|
|
64
|
+
# A magic number present in the overall doublewrite buffer structure,
|
65
|
+
# which identifies whether the space id is stored.
|
42
66
|
DOUBLEWRITE_SPACE_ID_STORED_MAGIC_N = 1783657386
|
43
67
|
|
68
|
+
# Read the overall doublewrite buffer structures
|
44
69
|
def doublewrite_info
|
45
70
|
c = cursor(pos_doublewrite_info)
|
46
71
|
{
|
47
|
-
:fseg => Innodb::FsegEntry.
|
72
|
+
:fseg => Innodb::FsegEntry.get_inode(@space, c),
|
48
73
|
:page_info => [
|
49
74
|
doublewrite_page_info(c),
|
50
75
|
doublewrite_page_info(c),
|
@@ -53,14 +78,15 @@ class Innodb::Page::TrxSys < Innodb::Page
|
|
53
78
|
}
|
54
79
|
end
|
55
80
|
|
81
|
+
# Read the TRX_SYS headers and other information.
|
56
82
|
def trx_sys
|
57
83
|
c = cursor(pos_trx_sys_header)
|
58
84
|
@trx_sys ||= {
|
59
|
-
:trx_id
|
60
|
-
:fseg
|
61
|
-
:binary_log
|
62
|
-
:master_log
|
63
|
-
:doublewrite
|
85
|
+
:trx_id => c.get_uint64,
|
86
|
+
:fseg => Innodb::FsegEntry.get_inode(@space, c),
|
87
|
+
:binary_log => mysql_log_info(pos_mysql_binary_log_info),
|
88
|
+
:master_log => mysql_log_info(pos_mysql_master_log_info),
|
89
|
+
:doublewrite => doublewrite_info,
|
64
90
|
}
|
65
91
|
end
|
66
92
|
|
data/lib/innodb/space.rb
CHANGED
@@ -22,7 +22,7 @@ class Innodb::Space
|
|
22
22
|
return nil unless (offset + PAGE_SIZE) <= @size
|
23
23
|
@file.seek(offset)
|
24
24
|
page_data = @file.read(PAGE_SIZE)
|
25
|
-
this_page = Innodb::Page.parse(page_data)
|
25
|
+
this_page = Innodb::Page.parse(self, page_data)
|
26
26
|
|
27
27
|
if this_page.type == :INDEX
|
28
28
|
this_page.record_describer = @record_describer
|
@@ -31,6 +31,11 @@ class Innodb::Space
|
|
31
31
|
this_page
|
32
32
|
end
|
33
33
|
|
34
|
+
# Get an Innodb::List object for a specific list by list name.
|
35
|
+
def list(name)
|
36
|
+
page(0).fsp_header[name]
|
37
|
+
end
|
38
|
+
|
34
39
|
# Get an Innodb::Index object for a specific index by root page number.
|
35
40
|
def index(root_page_number)
|
36
41
|
Innodb::Index.new(self, root_page_number)
|
data/lib/innodb/version.rb
CHANGED
data/lib/innodb/xdes.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
class Innodb::Xdes
|
2
|
+
PAGES_PER_EXTENT = 64
|
3
|
+
BITS_PER_PAGE = 2
|
4
|
+
BITMAP_SIZE = (PAGES_PER_EXTENT * BITS_PER_PAGE) / 8
|
5
|
+
ENTRY_SIZE = 8 + Innodb::List::NODE_SIZE + 4 + BITMAP_SIZE
|
6
|
+
|
7
|
+
STATES = {
|
8
|
+
1 => :free,
|
9
|
+
2 => :free_frag,
|
10
|
+
3 => :full_frag,
|
11
|
+
4 => :fseg,
|
12
|
+
}
|
13
|
+
|
14
|
+
def initialize(page, cursor)
|
15
|
+
@page = page
|
16
|
+
extent_number = (cursor.position - page.pos_xdes_array) / ENTRY_SIZE
|
17
|
+
start_page = page.offset + (extent_number * PAGES_PER_EXTENT)
|
18
|
+
@xdes = {
|
19
|
+
:start_page => start_page,
|
20
|
+
:fseg_id => cursor.get_uint64,
|
21
|
+
:this => {:page => page.offset, :offset => cursor.position},
|
22
|
+
:list => Innodb::List.get_node(cursor),
|
23
|
+
:state => STATES[cursor.get_uint32],
|
24
|
+
:bitmap => cursor.get_bytes(BITMAP_SIZE),
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
def xdes
|
29
|
+
@xdes
|
30
|
+
end
|
31
|
+
|
32
|
+
def prev_address
|
33
|
+
@xdes[:list][:prev]
|
34
|
+
end
|
35
|
+
|
36
|
+
def next_address
|
37
|
+
@xdes[:list][:next]
|
38
|
+
end
|
39
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: innodb_ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 1
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 7
|
9
|
+
- 1
|
10
|
+
version: 0.7.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Jeremy Cole
|
@@ -15,9 +15,24 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-12-
|
19
|
-
dependencies:
|
20
|
-
|
18
|
+
date: 2012-12-13 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: bindata
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 13
|
29
|
+
segments:
|
30
|
+
- 1
|
31
|
+
- 4
|
32
|
+
- 5
|
33
|
+
version: 1.4.5
|
34
|
+
type: :runtime
|
35
|
+
version_requirements: *id001
|
21
36
|
description: Library for parsing InnoDB data files in Ruby
|
22
37
|
email: jeremy@jcole.us
|
23
38
|
executables:
|
@@ -28,11 +43,13 @@ extensions: []
|
|
28
43
|
extra_rdoc_files: []
|
29
44
|
|
30
45
|
files:
|
46
|
+
- README.md
|
31
47
|
- lib/innodb.rb
|
32
48
|
- lib/innodb/cursor.rb
|
33
|
-
- lib/innodb/
|
49
|
+
- lib/innodb/field.rb
|
34
50
|
- lib/innodb/fseg_entry.rb
|
35
51
|
- lib/innodb/index.rb
|
52
|
+
- lib/innodb/list.rb
|
36
53
|
- lib/innodb/log.rb
|
37
54
|
- lib/innodb/log_block.rb
|
38
55
|
- lib/innodb/page.rb
|
@@ -43,6 +60,7 @@ files:
|
|
43
60
|
- lib/innodb/record_describer.rb
|
44
61
|
- lib/innodb/space.rb
|
45
62
|
- lib/innodb/version.rb
|
63
|
+
- lib/innodb/xdes.rb
|
46
64
|
- bin/innodb_log
|
47
65
|
- bin/innodb_space
|
48
66
|
homepage: http://jcole.us/
|
data/lib/innodb/free_list.rb
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
class Innodb::FreeList
|
2
|
-
FIL_ADDR_SIZE = 4 + 2
|
3
|
-
NODE_SIZE = 2 * FIL_ADDR_SIZE
|
4
|
-
BASE_NODE_SIZE = 4 + (2 * FIL_ADDR_SIZE)
|
5
|
-
|
6
|
-
def self.get_address(cursor)
|
7
|
-
{
|
8
|
-
:page => Innodb::Page.maybe_undefined(cursor.get_uint32),
|
9
|
-
:offset => cursor.get_uint16,
|
10
|
-
}
|
11
|
-
end
|
12
|
-
|
13
|
-
def self.get_node(cursor)
|
14
|
-
{
|
15
|
-
:prev => Innodb::FreeList::get_address(cursor),
|
16
|
-
:next => Innodb::FreeList::get_address(cursor),
|
17
|
-
}
|
18
|
-
end
|
19
|
-
|
20
|
-
def self.get_base_node(cursor)
|
21
|
-
{
|
22
|
-
:length => cursor.get_uint32,
|
23
|
-
:first => Innodb::FreeList::get_address(cursor),
|
24
|
-
:last => Innodb::FreeList::get_address(cursor),
|
25
|
-
}
|
26
|
-
end
|
27
|
-
end
|