innodb_ruby 0.9.13 → 0.11.0

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