innodb_ruby 0.9.13 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +5 -6
  3. data/bin/innodb_log +14 -19
  4. data/bin/innodb_space +592 -745
  5. data/lib/innodb.rb +5 -5
  6. data/lib/innodb/checksum.rb +26 -24
  7. data/lib/innodb/data_dictionary.rb +490 -550
  8. data/lib/innodb/data_type.rb +362 -325
  9. data/lib/innodb/field.rb +102 -89
  10. data/lib/innodb/fseg_entry.rb +22 -26
  11. data/lib/innodb/history.rb +21 -21
  12. data/lib/innodb/history_list.rb +72 -76
  13. data/lib/innodb/ibuf_bitmap.rb +36 -36
  14. data/lib/innodb/ibuf_index.rb +6 -2
  15. data/lib/innodb/index.rb +245 -275
  16. data/lib/innodb/inode.rb +166 -124
  17. data/lib/innodb/list.rb +191 -183
  18. data/lib/innodb/log.rb +139 -110
  19. data/lib/innodb/log_block.rb +100 -91
  20. data/lib/innodb/log_group.rb +53 -64
  21. data/lib/innodb/log_reader.rb +97 -96
  22. data/lib/innodb/log_record.rb +328 -279
  23. data/lib/innodb/lsn.rb +86 -81
  24. data/lib/innodb/page.rb +446 -291
  25. data/lib/innodb/page/blob.rb +82 -83
  26. data/lib/innodb/page/fsp_hdr_xdes.rb +174 -165
  27. data/lib/innodb/page/ibuf_bitmap.rb +34 -34
  28. data/lib/innodb/page/index.rb +965 -924
  29. data/lib/innodb/page/index_compressed.rb +34 -34
  30. data/lib/innodb/page/inode.rb +103 -112
  31. data/lib/innodb/page/sys.rb +13 -15
  32. data/lib/innodb/page/sys_data_dictionary_header.rb +81 -59
  33. data/lib/innodb/page/sys_ibuf_header.rb +45 -42
  34. data/lib/innodb/page/sys_rseg_header.rb +88 -82
  35. data/lib/innodb/page/trx_sys.rb +204 -182
  36. data/lib/innodb/page/undo_log.rb +106 -92
  37. data/lib/innodb/record.rb +121 -164
  38. data/lib/innodb/record_describer.rb +66 -68
  39. data/lib/innodb/space.rb +386 -391
  40. data/lib/innodb/stats.rb +33 -35
  41. data/lib/innodb/system.rb +149 -171
  42. data/lib/innodb/undo_log.rb +129 -107
  43. data/lib/innodb/undo_record.rb +255 -247
  44. data/lib/innodb/util/buffer_cursor.rb +81 -79
  45. data/lib/innodb/util/read_bits_at_offset.rb +2 -1
  46. data/lib/innodb/version.rb +2 -2
  47. data/lib/innodb/xdes.rb +144 -142
  48. metadata +112 -21
@@ -1,95 +1,109 @@
1
- # -*- encoding : utf-8 -*-
2
-
3
- class Innodb::Page::UndoLog < Innodb::Page
4
- def pos_undo_page_header
5
- pos_page_body
6
- end
7
-
8
- def size_undo_page_header
9
- 2 + 2 + 2 + Innodb::List::NODE_SIZE
10
- end
11
-
12
- def pos_undo_segment_header
13
- pos_undo_page_header + size_undo_page_header
14
- end
15
-
16
- def size_undo_segment_header
17
- 2 + 2 + Innodb::FsegEntry::SIZE + Innodb::List::BASE_NODE_SIZE
18
- end
19
-
20
- def pos_undo_logs
21
- pos_undo_segment_header + size_undo_segment_header
22
- end
23
-
24
- UNDO_PAGE_TYPES = {
25
- 1 => :insert,
26
- 2 => :update,
27
- }
28
-
29
- UNDO_SEGMENT_STATES = {
30
- 1 => :active,
31
- 2 => :cached,
32
- 3 => :to_free,
33
- 4 => :to_purge,
34
- 5 => :prepared,
35
- }
36
-
37
- def undo_page_header
38
- @undo_page_header ||=
39
- cursor(pos_undo_page_header).name("undo_page_header") do |c|
40
- {
41
- :type => c.name("type") { UNDO_PAGE_TYPES[c.get_uint16] },
42
- :latest_log_record_offset => c.name("latest_log_record_offset") { c.get_uint16 },
43
- :free_offset => c.name("free_offset") { c.get_uint16 },
44
- :page_list_node => c.name("page_list") { Innodb::List.get_node(c) },
45
- }
1
+ # frozen_string_literal: true
2
+
3
+ module Innodb
4
+ class Page
5
+ class UndoLog < Page
6
+ specialization_for :UNDO_LOG
7
+
8
+ PageHeader = Struct.new(
9
+ :type,
10
+ :latest_log_record_offset,
11
+ :free_offset,
12
+ :page_list_node,
13
+ keyword_init: true
14
+ )
15
+
16
+ SegmentHeader = Struct.new(
17
+ :state,
18
+ :last_log_offset,
19
+ :fseg,
20
+ :page_list,
21
+ keyword_init: true
22
+ )
23
+
24
+ def pos_undo_page_header
25
+ pos_page_body
26
+ end
27
+
28
+ def size_undo_page_header
29
+ 2 + 2 + 2 + Innodb::List::NODE_SIZE
30
+ end
31
+
32
+ def pos_undo_segment_header
33
+ pos_undo_page_header + size_undo_page_header
34
+ end
35
+
36
+ def size_undo_segment_header
37
+ 2 + 2 + Innodb::FsegEntry::SIZE + Innodb::List::BASE_NODE_SIZE
38
+ end
39
+
40
+ def pos_undo_logs
41
+ pos_undo_segment_header + size_undo_segment_header
42
+ end
43
+
44
+ UNDO_PAGE_TYPES = {
45
+ 1 => :insert,
46
+ 2 => :update,
47
+ }.freeze
48
+
49
+ UNDO_SEGMENT_STATES = {
50
+ 1 => :active,
51
+ 2 => :cached,
52
+ 3 => :to_free,
53
+ 4 => :to_purge,
54
+ 5 => :prepared,
55
+ }.freeze
56
+
57
+ def undo_page_header
58
+ @undo_page_header ||= cursor(pos_undo_page_header).name("undo_page_header") do |c|
59
+ PageHeader.new(
60
+ type: c.name("type") { UNDO_PAGE_TYPES[c.read_uint16] },
61
+ latest_log_record_offset: c.name("latest_log_record_offset") { c.read_uint16 },
62
+ free_offset: c.name("free_offset") { c.read_uint16 },
63
+ page_list_node: c.name("page_list") { Innodb::List.get_node(c) }
64
+ )
65
+ end
66
+ end
67
+
68
+ def prev_address
69
+ undo_page_header[:page_list_node][:prev]
70
+ end
71
+
72
+ def next_address
73
+ undo_page_header[:page_list_node][:next]
74
+ end
75
+
76
+ def undo_segment_header
77
+ @undo_segment_header ||= cursor(pos_undo_segment_header).name("undo_segment_header") do |c|
78
+ SegmentHeader.new(
79
+ state: c.name("state") { UNDO_SEGMENT_STATES[c.read_uint16] },
80
+ last_log_offset: c.name("last_log_offset") { c.read_uint16 },
81
+ fseg: c.name("fseg") { Innodb::FsegEntry.get_inode(@space, c) },
82
+ page_list: c.name("page_list") { Innodb::List::UndoPage.new(@space, Innodb::List.get_base_node(c)) }
83
+ )
84
+ end
85
+ end
86
+
87
+ def undo_log(pos)
88
+ Innodb::UndoLog.new(self, pos)
89
+ end
90
+
91
+ # Dump the contents of a page for debugging purposes.
92
+ def dump
93
+ super
94
+
95
+ puts "undo page header:"
96
+ pp undo_page_header
97
+ puts
98
+
99
+ puts "undo segment header:"
100
+ pp undo_segment_header
101
+ puts
102
+
103
+ puts "last undo log:"
104
+ undo_log(undo_segment_header[:last_log_offset]).dump unless undo_segment_header[:last_log_offset].zero?
105
+ puts
106
+ end
46
107
  end
47
108
  end
48
-
49
- def prev_address
50
- undo_page_header[:page_list_node][:prev]
51
- end
52
-
53
- def next_address
54
- undo_page_header[:page_list_node][:next]
55
- end
56
-
57
- def undo_segment_header
58
- @undo_segment_header ||=
59
- cursor(pos_undo_segment_header).name("undo_segment_header") do |c|
60
- {
61
- :state => c.name("state") { UNDO_SEGMENT_STATES[c.get_uint16] },
62
- :last_log_offset => c.name("last_log_offset") { c.get_uint16 },
63
- :fseg => c.name("fseg") { Innodb::FsegEntry.get_inode(@space, c) },
64
- :page_list => c.name("page_list") {
65
- Innodb::List::UndoPage.new(@space, Innodb::List.get_base_node(c))
66
- },
67
- }
68
- end
69
- end
70
-
71
- def undo_log(pos)
72
- Innodb::UndoLog.new(self, pos)
73
- end
74
-
75
- # Dump the contents of a page for debugging purposes.
76
- def dump
77
- super
78
-
79
- puts "undo page header:"
80
- pp undo_page_header
81
- puts
82
-
83
- puts "undo segment header:"
84
- pp undo_segment_header
85
- puts
86
-
87
- puts "last undo log:"
88
- if undo_segment_header[:last_log_offset] != 0
89
- undo_log(undo_segment_header[:last_log_offset]).dump
90
- end
91
- puts
92
- end
93
109
  end
94
-
95
- Innodb::Page::SPECIALIZED_CLASSES[:UNDO_LOG] = Innodb::Page::UndoLog
data/lib/innodb/record.rb CHANGED
@@ -1,199 +1,156 @@
1
- # -*- encoding : utf-8 -*-
1
+ # frozen_string_literal: true
2
2
 
3
- class Innodb::Record
4
- attr_reader :page
5
- attr_accessor :record
3
+ require "forwardable"
6
4
 
7
- def initialize(page, record)
8
- @page = page
9
- @record = record
10
- end
11
-
12
- def header
13
- record[:header]
14
- end
15
-
16
- def next
17
- header[:next]
18
- end
19
-
20
- def type
21
- header[:type]
22
- end
5
+ module Innodb
6
+ class Record
7
+ extend Forwardable
23
8
 
24
- def heap_number
25
- header[:heap_number]
26
- end
27
-
28
- def n_owned
29
- header[:n_owned]
30
- end
31
-
32
- def deleted?
33
- header[:deleted]
34
- end
35
-
36
- def min_rec?
37
- header[:min_rec]
38
- end
9
+ attr_reader :page
10
+ attr_accessor :record
39
11
 
40
- def offset
41
- record[:offset]
42
- end
43
-
44
- def length
45
- record[:length]
46
- end
47
-
48
- def next
49
- record[:next]
50
- end
51
-
52
- def key
53
- record[:key]
54
- end
12
+ def initialize(page, record)
13
+ @page = page
14
+ @record = record
15
+ end
55
16
 
56
- def key_string
57
- key && key.map { |r| "%s=%s" % [r[:name], r[:value].inspect] }.join(", ")
58
- end
17
+ def_delegator :record, :header
18
+ def_delegator :record, :offset
19
+ def_delegator :record, :length
20
+ def_delegator :record, :next
21
+ def_delegator :record, :key
22
+ def_delegator :record, :row
23
+ def_delegator :record, :transaction_id
24
+ def_delegator :record, :roll_pointer
25
+ def_delegator :record, :child_page_number
26
+
27
+ def_delegator :header, :type
28
+ def_delegator :header, :heap_number
29
+ def_delegator :header, :n_owned
30
+ def_delegator :header, :heap_number
31
+ def_delegator :header, :deleted?
32
+ def_delegator :header, :min_rec?
33
+
34
+ def key_string
35
+ key&.map { |r| "%s=%s" % [r.name, r.value.inspect] }&.join(", ")
36
+ end
59
37
 
60
- def row
61
- record[:row]
62
- end
38
+ def row_string
39
+ row&.map { |r| "%s=%s" % [r.name, r.value.inspect] }&.join(", ")
40
+ end
63
41
 
64
- def row_string
65
- row && row.map { |r| "%s=%s" % [r[:name], r[:value].inspect] }.join(", ")
66
- end
42
+ def undo
43
+ return nil unless roll_pointer
44
+ return unless (innodb_system = @page.space.innodb_system)
67
45
 
68
- def transaction_id
69
- record[:transaction_id]
70
- end
46
+ undo_page = innodb_system.system_space.page(roll_pointer.undo_log.page)
47
+ return unless undo_page
71
48
 
72
- def roll_pointer
73
- record[:roll_pointer]
74
- end
49
+ new_undo_record = Innodb::UndoRecord.new(undo_page, roll_pointer.undo_log.offset)
50
+ new_undo_record.index_page = page
51
+ new_undo_record
52
+ end
75
53
 
76
- def undo
77
- return nil unless roll_pointer
54
+ def each_undo_record
55
+ return enum_for(:each_undo_record) unless block_given?
78
56
 
79
- if innodb_system = @page.space.innodb_system
80
- undo_space = innodb_system.system_space
81
- if undo_page = undo_space.page(roll_pointer[:undo_log][:page])
82
- new_undo_record = Innodb::UndoRecord.new(undo_page, roll_pointer[:undo_log][:offset])
83
- new_undo_record.index_page = page
84
- new_undo_record
57
+ undo_record = undo
58
+ while undo_record
59
+ yield undo_record
60
+ undo_record = undo_record.prev_by_history
85
61
  end
86
- end
87
- end
88
-
89
- def each_undo_record
90
- unless block_given?
91
- return enum_for(:each_undo_record)
92
- end
93
62
 
94
- undo_record = undo
95
- while undo_record
96
- yield undo_record
97
- undo_record = undo_record.prev_by_history
63
+ nil
98
64
  end
99
65
 
100
- nil
101
- end
102
-
103
- def child_page_number
104
- record[:child_page_number]
105
- end
106
-
107
- def string
108
- if child_page_number
109
- "(%s) → #%s" % [key_string, child_page_number]
110
- else
111
- "(%s) → (%s)" % [key_string, row_string]
66
+ def string
67
+ if child_page_number
68
+ "(%s) → #%s" % [key_string, child_page_number]
69
+ else
70
+ "(%s) → (%s)" % [key_string, row_string]
71
+ end
112
72
  end
113
- end
114
73
 
115
- def uncached_fields
116
- fields_hash = {}
117
- [:key, :row].each do |group|
118
- if record[group]
119
- record[group].each do |column|
120
- fields_hash[column[:name]] = column[:value]
74
+ def uncached_fields
75
+ fields_hash = {}
76
+ %i[key row].each do |group|
77
+ record[group]&.each do |column|
78
+ fields_hash[column.name] = column.value
121
79
  end
122
80
  end
81
+ fields_hash
123
82
  end
124
- fields_hash
125
- end
126
83
 
127
- def fields
128
- @fields ||= uncached_fields
129
- end
84
+ def fields
85
+ @fields ||= uncached_fields
86
+ end
87
+
88
+ # Compare two arrays of fields to determine if they are equal. This follows
89
+ # the same comparison rules as strcmp and others:
90
+ # 0 = a is equal to b
91
+ # -1 = a is less than b
92
+ # +1 = a is greater than b
93
+ def compare_key(other_key)
94
+ Innodb::Stats.increment :compare_key
95
+
96
+ return 0 if other_key.nil? && key.nil?
97
+ return -1 if other_key.nil? || (!key.nil? && other_key.size < key.size)
98
+ return +1 if key.nil? || (!other_key.nil? && other_key.size > key.size)
99
+
100
+ key.each_index do |i|
101
+ Innodb::Stats.increment :compare_key_field_comparison
102
+ return -1 if other_key[i] < key[i].value
103
+ return +1 if other_key[i] > key[i].value
104
+ end
130
105
 
131
- # Compare two arrays of fields to determine if they are equal. This follows
132
- # the same comparison rules as strcmp and others:
133
- # 0 = a is equal to b
134
- # -1 = a is less than b
135
- # +1 = a is greater than b
136
- def compare_key(other_key)
137
- Innodb::Stats.increment :compare_key
138
-
139
- return 0 if other_key.nil? && key.nil?
140
- return -1 if other_key.nil? || (!key.nil? && other_key.size < key.size)
141
- return +1 if key.nil? || (!other_key.nil? && other_key.size > key.size)
142
-
143
- key.each_index do |i|
144
- Innodb::Stats.increment :compare_key_field_comparison
145
- return -1 if other_key[i] < key[i][:value]
146
- return +1 if other_key[i] > key[i][:value]
106
+ 0
147
107
  end
148
108
 
149
- return 0
150
- end
109
+ def dump
110
+ puts "Record at offset %i" % offset
111
+ puts
151
112
 
152
- def dump
153
- puts "Record at offset %i" % offset
154
- puts
155
-
156
- puts "Header:"
157
- puts " %-20s: %i" % ["Next record offset", header[:next]]
158
- puts " %-20s: %i" % ["Heap number", header[:heap_number]]
159
- puts " %-20s: %s" % ["Type", header[:type]]
160
- puts " %-20s: %s" % ["Deleted", header[:deleted]]
161
- puts " %-20s: %s" % ["Length", header[:length]]
162
- puts
163
-
164
- if page.leaf?
165
- puts "System fields:"
166
- puts " Transaction ID: %s" % transaction_id
167
- puts " Roll Pointer:"
168
- puts " Undo Log: page %i, offset %i" % [
169
- roll_pointer[:undo_log][:page],
170
- roll_pointer[:undo_log][:offset],
171
- ]
172
- puts " Rollback Segment ID: %i" % roll_pointer[:rseg_id]
173
- puts " Insert: %s" % roll_pointer[:is_insert]
113
+ puts "Header:"
114
+ puts " %-20s: %i" % ["Next record offset", header.next]
115
+ puts " %-20s: %i" % ["Heap number", header.heap_number]
116
+ puts " %-20s: %s" % ["Type", header.type]
117
+ puts " %-20s: %s" % ["Deleted", header.deleted?]
118
+ puts " %-20s: %s" % ["Length", header.length]
174
119
  puts
175
- end
176
120
 
177
- puts "Key fields:"
178
- key.each do |field|
179
- puts " %s: %s" % [
180
- field[:name],
181
- field[:value].inspect,
182
- ]
183
- end
184
- puts
121
+ if page.leaf?
122
+ puts "System fields:"
123
+ puts " Transaction ID: %s" % transaction_id
124
+ puts " Roll Pointer:"
125
+ puts " Undo Log: page %i, offset %i" % [
126
+ roll_pointer.undo_log.page,
127
+ roll_pointer.undo_log.offset,
128
+ ]
129
+ puts " Rollback Segment ID: %i" % roll_pointer.rseg_id
130
+ puts " Insert: %s" % roll_pointer.is_insert
131
+ puts
132
+ end
185
133
 
186
- if page.leaf?
187
- puts "Non-key fields:"
188
- row.each do |field|
134
+ puts "Key fields:"
135
+ key.each do |field|
189
136
  puts " %s: %s" % [
190
- field[:name],
191
- field[:value].inspect,
137
+ field.name,
138
+ field.value.inspect,
192
139
  ]
193
140
  end
194
141
  puts
195
- else
196
- puts "Child page number: %i" % child_page_number
142
+
143
+ if page.leaf?
144
+ puts "Non-key fields:"
145
+ row.each do |field|
146
+ puts " %s: %s" % [
147
+ field.name,
148
+ field.value.inspect,
149
+ ]
150
+ end
151
+ else
152
+ puts "Child page number: %i" % child_page_number
153
+ end
197
154
  puts
198
155
  end
199
156
  end