innodb_ruby 0.6.6 → 0.7.1

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.
@@ -1,17 +1,30 @@
1
- require "innodb/free_list"
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::FreeList::NODE_SIZE
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::FreeList::BASE_NODE_SIZE) +
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 uint32_array(size, cursor)
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::FreeList.get_base_node(cursor),
31
- :not_full => Innodb::FreeList.get_base_node(cursor),
32
- :full => Innodb::FreeList.get_base_node(cursor),
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 => uint32_array(FRAG_ARRAY_N_SLOTS, cursor),
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
@@ -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
- def pos_mysql_binary_log_info
7
- size - 1000
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.get_entry(c),
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 => c.get_uint64,
60
- :fseg => Innodb::FsegEntry.get_entry(c),
61
- :binary_log => mysql_log_info(pos_mysql_binary_log_info),
62
- :master_log => mysql_log_info(pos_mysql_master_log_info),
63
- :doublewrite => doublewrite_info,
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
 
@@ -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)
@@ -1,3 +1,3 @@
1
1
  module Innodb
2
- VERSION = "0.6.6"
2
+ VERSION = "0.7.1"
3
3
  end
@@ -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: 11
4
+ hash: 1
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 6
9
- - 6
10
- version: 0.6.6
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-07 00:00:00 Z
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/free_list.rb
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/
@@ -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