Class: Innodb::Cursor

Inherits:
Object
  • Object
show all
Defined in:
lib/innodb/cursor.rb

Overview

A cursor to walk through InnoDB data structures to read fields.

Instance Method Summary collapse

Constructor Details

#initialize(buffer, offset) ⇒ Cursor

Returns a new instance of Cursor.



5
6
7
8
9
# File 'lib/innodb/cursor.rb', line 5

def initialize(buffer, offset)
  @buffer = buffer
  @cursor = [ offset ]
  @direction = :forward
end

Instance Method Details

#adjust(relative_offset) ⇒ Object

Adjust the current cursor to a new relative position.



35
36
37
38
# File 'lib/innodb/cursor.rb', line 35

def adjust(relative_offset)
  @cursor[0] += relative_offset
  self
end

#backwardObject

Set the direction of the cursor to “backward”.



18
19
20
21
# File 'lib/innodb/cursor.rb', line 18

def backward
  @direction = :backward
  self
end

#forwardObject

Set the direction of the cursor to “forward”.



12
13
14
15
# File 'lib/innodb/cursor.rb', line 12

def forward
  @direction = :forward
  self
end

#get_bit_array(num_bits) ⇒ Object

Read an array of 1-bit integers.



221
222
223
224
225
226
# File 'lib/innodb/cursor.rb', line 221

def get_bit_array(num_bits)
  size = (num_bits + 7) / 8
  data = read_and_advance(size)
  bit_array = BinData::Array.new(:type => :bit1, :initial_length => size * 8)
  bit_array.read(data).to_ary
end

#get_bytes(length) ⇒ Object

Return raw bytes.



82
83
84
# File 'lib/innodb/cursor.rb', line 82

def get_bytes(length)
  read_and_advance(length)
end

#get_hex(length) ⇒ Object

Return raw bytes as hex.



87
88
89
# File 'lib/innodb/cursor.rb', line 87

def get_hex(length)
  read_and_advance(length).bytes.map { |c| "%02x" % c }.join
end

#get_i_sint16Object

Read an InnoDB-munged signed 16-bit integer.



179
180
181
182
# File 'lib/innodb/cursor.rb', line 179

def get_i_sint16
  data = read_and_advance(2)
  BinData::Int16be.read(data) ^ (-1 << 15)
end

#get_i_sint24Object

Read an InnoDB-munged signed 24-bit integer.



185
186
187
188
# File 'lib/innodb/cursor.rb', line 185

def get_i_sint24
  data = read_and_advance(3)
  BinData::Int24be.read(data) ^ (-1 << 23)
end

#get_i_sint32Object

Read an InnoDB-munged signed 32-bit integer.



191
192
193
194
# File 'lib/innodb/cursor.rb', line 191

def get_i_sint32
  data = read_and_advance(4)
  BinData::Int32be.read(data) ^ (-1 << 31)
end

#get_i_sint64Object

Read an InnoDB-munged signed 64-bit integer.



197
198
199
200
# File 'lib/innodb/cursor.rb', line 197

def get_i_sint64
  data = read_and_advance(8)
  BinData::Int64be.read(data) ^ (-1 << 63)
end

#get_i_sint8Object

Read an InnoDB-munged signed 8-bit integer.



173
174
175
176
# File 'lib/innodb/cursor.rb', line 173

def get_i_sint8
  data = read_and_advance(1)
  BinData::Int8.read(data) ^ (-1 << 7)
end

#get_i_sint_by_size(size) ⇒ Object

Read an InnoDB-munged signed integer given its size in bytes.



203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'lib/innodb/cursor.rb', line 203

def get_i_sint_by_size(size)
  case size
  when 1
    get_i_sint8
  when 2
    get_i_sint16
  when 3
    get_i_sint24
  when 4
    get_i_sint32
  when 8
    get_i_sint64
  else
    raise "Not implemented"
  end
end

#get_ic_uint32Object

Read an InnoDB-compressed unsigned 32-bit integer.



152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/innodb/cursor.rb', line 152

def get_ic_uint32
  flag = peek { get_uint8 }

  case
  when flag < 0x80
    get_uint8
  when flag < 0xc0
    get_uint16 & 0x7fff
  when flag < 0xe0
    get_uint24 & 0x3fffff
  when flag < 0xf0
    get_uint32 & 0x1fffffff
  when flag == 0xf0
    adjust(+1) # Skip the flag.
    get_uint32
  else
    raise "Invalid flag #{flag.to_s(16)} seen"
  end
end

#get_sint16(offset = nil) ⇒ Object

Read a big-endian signed 16-bit integer.



106
107
108
109
110
# File 'lib/innodb/cursor.rb', line 106

def get_sint16(offset=nil)
  seek(offset)
  data = read_and_advance(2)
  BinData::Int16be.read(data)
end

#get_uint16(offset = nil) ⇒ Object

Read a big-endian unsigned 16-bit integer.



99
100
101
102
103
# File 'lib/innodb/cursor.rb', line 99

def get_uint16(offset=nil)
  seek(offset)
  data = read_and_advance(2)
  BinData::Uint16be.read(data)
end

#get_uint24(offset = nil) ⇒ Object

Read a big-endian unsigned 24-bit integer.



113
114
115
116
117
# File 'lib/innodb/cursor.rb', line 113

def get_uint24(offset=nil)
  seek(offset)
  data = read_and_advance(3)
  BinData::Uint24be.read(data)
end

#get_uint32(offset = nil) ⇒ Object

Read a big-endian unsigned 32-bit integer.



120
121
122
123
124
# File 'lib/innodb/cursor.rb', line 120

def get_uint32(offset=nil)
  seek(offset)
  data = read_and_advance(4)
  BinData::Uint32be.read(data)
end

#get_uint64(offset = nil) ⇒ Object

Read a big-endian unsigned 64-bit integer.



127
128
129
130
131
# File 'lib/innodb/cursor.rb', line 127

def get_uint64(offset=nil)
  seek(offset)
  data = read_and_advance(8)
  BinData::Uint64be.read(data)
end

#get_uint8(offset = nil) ⇒ Object

Read an unsigned 8-bit integer.



92
93
94
95
96
# File 'lib/innodb/cursor.rb', line 92

def get_uint8(offset=nil)
  seek(offset)
  data = read_and_advance(1)
  BinData::Uint8.read(data)
end

#get_uint_by_size(size) ⇒ Object

Read a big-endian unsigned integer given its size in bytes.



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/innodb/cursor.rb', line 134

def get_uint_by_size(size)
  case size
  when 1
    get_uint8
  when 2
    get_uint16
  when 3
    get_uint24
  when 4
    get_uint32
  when 8
    get_uint64
  else
    raise "Not implemented"
  end
end

#peekObject

Execute a block and restore the cursor to the previous position after the block returns. Return the block’s return value after restoring the cursor.



56
57
58
59
60
61
62
# File 'lib/innodb/cursor.rb', line 56

def peek
  raise "No block given" unless block_given?
  push
  result = yield
  pop
  result
end

#popObject

Restore the last cursor position.



47
48
49
50
51
# File 'lib/innodb/cursor.rb', line 47

def pop
  raise "No cursors to pop" unless @cursor.size > 1
  @cursor.shift
  self
end

#positionObject

Return the position of the current cursor.



24
25
26
# File 'lib/innodb/cursor.rb', line 24

def position
  @cursor[0]
end

#push(offset = nil) ⇒ Object

Save the current cursor position and start a new (nested, stacked) cursor.



41
42
43
44
# File 'lib/innodb/cursor.rb', line 41

def push(offset=nil)
  @cursor.unshift(offset.nil? ? @cursor[0] : offset)
  self
end

#read_and_advance(length) ⇒ Object

Read a number of bytes forwards or backwards from the current cursor position and adjust the cursor position by that amount.



66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/innodb/cursor.rb', line 66

def read_and_advance(length)
  data = nil
  #print "data(#{@cursor[0]}..."
  case @direction
  when :forward
    data = @buffer.data(@cursor[0], length)
    adjust(length)
  when :backward
    adjust(-length)
    data = @buffer.data(@cursor[0], length)
  end
  #puts "#{@cursor[0]}) = #{data.bytes.map { |n| "%02x" % n }.join}"
  data
end

#seek(offset) ⇒ Object

Move the current cursor to a new absolute position.



29
30
31
32
# File 'lib/innodb/cursor.rb', line 29

def seek(offset)
  @cursor[0] = offset if offset
  self
end