class Innodb::LogReader

Constants

Context

Attributes

checksum[RW]

Whether to checksum blocks. TODO: Hmm, nothing seems to actually set this.

Public Class Methods

new(lsn, group) click to toggle source
# File lib/innodb/log_reader.rb, line 23
def initialize(lsn, group)
  @group = group
  @context = Context.new(buffer: String.new, buffer_lsn: lsn.dup, record_lsn: lsn.dup)
end

Public Instance Methods

each_record(follow, wait = 0.5) { |record| ... } click to toggle source

Call the given block once for each record in the log until the end of the log (or a corrupted block) is reached. If the follow argument is true, retry.

# File lib/innodb/log_reader.rb, line 54
def each_record(follow, wait = 0.5)
  loop { yield record }
rescue EOFError, ChecksumError
  sleep(wait) && retry if follow
end
record() click to toggle source

Read a record.

# File lib/innodb/log_reader.rb, line 43
def record
  cursor = BufferCursor.new(self, 0)
  record = Innodb::LogRecord.new
  record.read(cursor)
  record.lsn = reposition(cursor.position)
  record
end
seek(lsn_no) click to toggle source

Seek to record starting position.

# File lib/innodb/log_reader.rb, line 29
def seek(lsn_no)
  check_lsn_no(lsn_no)
  @context.buffer = String.new
  @context.buffer_lsn.reposition(lsn_no, @group)
  @context.record_lsn = @context.buffer_lsn.dup
  self
end
slice(position, length) click to toggle source

Read a slice of log data (that is, log data used for records).

# File lib/innodb/log_reader.rb, line 61
def slice(position, length)
  buffer = @context.buffer
  length = position + length

  preload(length) if length > buffer.size

  buffer.slice(position, length - position)
end
tell() click to toggle source

Returns the current LSN starting position.

# File lib/innodb/log_reader.rb, line 38
def tell
  @context.record_lsn.no
end

Private Instance Methods

check_lsn_no(lsn_no) click to toggle source

Check if LSN points to where records may be located.

# File lib/innodb/log_reader.rb, line 73
def check_lsn_no(lsn_no)
  lsn = @context.record_lsn.dup
  lsn.reposition(lsn_no, @group)
  raise "LSN #{lsn_no} is out of bounds" unless lsn.record?(@group)
end
get_block(lsn) click to toggle source

Reads the log block at the given LSN position.

# File lib/innodb/log_reader.rb, line 89
def get_block(lsn)
  log_no, block_no, block_offset = lsn.location(@group)
  [@group.log(log_no).block(block_no), block_offset]
end
preload(size) click to toggle source

Preload the log buffer with enough data to satisfy the requested amount.

# File lib/innodb/log_reader.rb, line 95
def preload(size)
  buffer = @context.buffer
  buffer_lsn = @context.buffer_lsn

  # If reading for the first time, offset points to the start of the
  # record (somewhere in the block). Otherwise, the block is read as
  # a whole and offset points to the start of the next block to read.
  while buffer.size < size
    block, offset = get_block(buffer_lsn)
    break if checksum && (corrupt = block.corrupt?)

    data = offset.zero? ? block.data : block.data(offset)
    data_length = block.header[:data_length]
    buffer << data
    buffer_lsn.advance(data_length - offset, @group)
    break if data_length < Innodb::LogBlock::BLOCK_SIZE
  end

  raise ChecksumError, "Block is corrupted" if corrupt
  raise EOFError, "End of log reached" if buffer.size < size
end
reposition(length) click to toggle source

Reposition to the beginning of the next record.

# File lib/innodb/log_reader.rb, line 80
def reposition(length)
  start_lsn_no = @context.record_lsn.no
  delta_lsn_no = @context.record_lsn.delta(length)
  @context.record_lsn.advance(delta_lsn_no, @group)
  @context.buffer.slice!(0, length)
  [start_lsn_no, start_lsn_no + delta_lsn_no]
end