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.
@@ -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