innodb_ruby 0.9.16 → 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 +5 -5
  2. data/README.md +5 -6
  3. data/bin/innodb_log +13 -18
  4. data/bin/innodb_space +377 -757
  5. data/lib/innodb.rb +4 -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 -326
  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 -276
  16. data/lib/innodb/inode.rb +154 -155
  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 +417 -414
  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 +964 -943
  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 -160
  38. data/lib/innodb/record_describer.rb +66 -68
  39. data/lib/innodb/space.rb +380 -418
  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 +80 -11
@@ -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,195 +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 type
17
- header[:type]
18
- end
19
-
20
- def heap_number
21
- header[:heap_number]
22
- end
23
-
24
- def n_owned
25
- header[:n_owned]
26
- end
27
-
28
- def deleted?
29
- header[:deleted]
30
- end
31
-
32
- def min_rec?
33
- header[:min_rec]
34
- end
5
+ module Innodb
6
+ class Record
7
+ extend Forwardable
35
8
 
36
- def offset
37
- record[:offset]
38
- end
39
-
40
- def length
41
- record[:length]
42
- end
9
+ attr_reader :page
10
+ attr_accessor :record
43
11
 
44
- def next
45
- record[:next]
46
- end
47
-
48
- def key
49
- record[:key]
50
- end
12
+ def initialize(page, record)
13
+ @page = page
14
+ @record = record
15
+ end
51
16
 
52
- def key_string
53
- key && key.map { |r| "%s=%s" % [r[:name], r[:value].inspect] }.join(", ")
54
- 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
55
37
 
56
- def row
57
- record[:row]
58
- end
38
+ def row_string
39
+ row&.map { |r| "%s=%s" % [r.name, r.value.inspect] }&.join(", ")
40
+ end
59
41
 
60
- def row_string
61
- row && row.map { |r| "%s=%s" % [r[:name], r[:value].inspect] }.join(", ")
62
- end
42
+ def undo
43
+ return nil unless roll_pointer
44
+ return unless (innodb_system = @page.space.innodb_system)
63
45
 
64
- def transaction_id
65
- record[:transaction_id]
66
- end
46
+ undo_page = innodb_system.system_space.page(roll_pointer.undo_log.page)
47
+ return unless undo_page
67
48
 
68
- def roll_pointer
69
- record[:roll_pointer]
70
- 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
71
53
 
72
- def undo
73
- return nil unless roll_pointer
54
+ def each_undo_record
55
+ return enum_for(:each_undo_record) unless block_given?
74
56
 
75
- if innodb_system = @page.space.innodb_system
76
- undo_space = innodb_system.system_space
77
- if undo_page = undo_space.page(roll_pointer[:undo_log][:page])
78
- new_undo_record = Innodb::UndoRecord.new(undo_page, roll_pointer[:undo_log][:offset])
79
- new_undo_record.index_page = page
80
- new_undo_record
57
+ undo_record = undo
58
+ while undo_record
59
+ yield undo_record
60
+ undo_record = undo_record.prev_by_history
81
61
  end
82
- end
83
- end
84
62
 
85
- def each_undo_record
86
- unless block_given?
87
- return enum_for(:each_undo_record)
63
+ nil
88
64
  end
89
65
 
90
- undo_record = undo
91
- while undo_record
92
- yield undo_record
93
- undo_record = undo_record.prev_by_history
94
- end
95
-
96
- nil
97
- end
98
-
99
- def child_page_number
100
- record[:child_page_number]
101
- end
102
-
103
- def string
104
- if child_page_number
105
- "(%s) → #%s" % [key_string, child_page_number]
106
- else
107
- "(%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
108
72
  end
109
- end
110
73
 
111
- def uncached_fields
112
- fields_hash = {}
113
- [:key, :row].each do |group|
114
- if record[group]
115
- record[group].each do |column|
116
- 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
117
79
  end
118
80
  end
81
+ fields_hash
119
82
  end
120
- fields_hash
121
- end
122
83
 
123
- def fields
124
- @fields ||= uncached_fields
125
- 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
126
105
 
127
- # Compare two arrays of fields to determine if they are equal. This follows
128
- # the same comparison rules as strcmp and others:
129
- # 0 = a is equal to b
130
- # -1 = a is less than b
131
- # +1 = a is greater than b
132
- def compare_key(other_key)
133
- Innodb::Stats.increment :compare_key
134
-
135
- return 0 if other_key.nil? && key.nil?
136
- return -1 if other_key.nil? || (!key.nil? && other_key.size < key.size)
137
- return +1 if key.nil? || (!other_key.nil? && other_key.size > key.size)
138
-
139
- key.each_index do |i|
140
- Innodb::Stats.increment :compare_key_field_comparison
141
- return -1 if other_key[i] < key[i][:value]
142
- return +1 if other_key[i] > key[i][:value]
106
+ 0
143
107
  end
144
108
 
145
- return 0
146
- end
109
+ def dump
110
+ puts "Record at offset %i" % offset
111
+ puts
147
112
 
148
- def dump
149
- puts "Record at offset %i" % offset
150
- puts
151
-
152
- puts "Header:"
153
- puts " %-20s: %i" % ["Next record offset", header[:next]]
154
- puts " %-20s: %i" % ["Heap number", header[:heap_number]]
155
- puts " %-20s: %s" % ["Type", header[:type]]
156
- puts " %-20s: %s" % ["Deleted", header[:deleted]]
157
- puts " %-20s: %s" % ["Length", header[:length]]
158
- puts
159
-
160
- if page.leaf?
161
- puts "System fields:"
162
- puts " Transaction ID: %s" % transaction_id
163
- puts " Roll Pointer:"
164
- puts " Undo Log: page %i, offset %i" % [
165
- roll_pointer[:undo_log][:page],
166
- roll_pointer[:undo_log][:offset],
167
- ]
168
- puts " Rollback Segment ID: %i" % roll_pointer[:rseg_id]
169
- 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]
170
119
  puts
171
- end
172
120
 
173
- puts "Key fields:"
174
- key.each do |field|
175
- puts " %s: %s" % [
176
- field[:name],
177
- field[:value].inspect,
178
- ]
179
- end
180
- 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
181
133
 
182
- if page.leaf?
183
- puts "Non-key fields:"
184
- row.each do |field|
134
+ puts "Key fields:"
135
+ key.each do |field|
185
136
  puts " %s: %s" % [
186
- field[:name],
187
- field[:value].inspect,
137
+ field.name,
138
+ field.value.inspect,
188
139
  ]
189
140
  end
190
141
  puts
191
- else
192
- 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
193
154
  puts
194
155
  end
195
156
  end