class Innodb::Log

Constants

Checkpoint
CheckpointGroup
CheckpointSet
LOG_CHECKPOINT_GROUPS

Maximum number of log group checkpoints.

LOG_HEADER_BLOCKS

Number of blocks in the log file header.

LOG_HEADER_BLOCK_MAP

A map of the name and position of the blocks that form the log header.

LOG_HEADER_SIZE

The size in bytes of the log file header.

Attributes

blocks[R]

The number of blocks in the log.

capacity[R]

The log capacity (in bytes).

size[R]

The size (in bytes) of the log.

Public Class Methods

new(filename) click to toggle source

Open a log file.

# File lib/innodb/log.rb, line 58
def initialize(filename)
  @file = File.open(filename)
  @size = @file.stat.size
  @blocks = (@size / Innodb::LogBlock::BLOCK_SIZE) - LOG_HEADER_BLOCKS
  @capacity = @blocks * Innodb::LogBlock::BLOCK_SIZE
end

Public Instance Methods

block(block_index) click to toggle source

Return a log block with a given block index as an InnoDB::LogBlock object. Blocks are indexed after the log file header, starting from 0.

# File lib/innodb/log.rb, line 139
def block(block_index)
  return nil unless block_index.between?(0, @blocks - 1)

  offset = (LOG_HEADER_BLOCKS + block_index.to_i) * Innodb::LogBlock::BLOCK_SIZE
  Innodb::LogBlock.new(block_data(offset))
end
block_cursor(offset) click to toggle source

Get a cursor to a block in a given offset of the log.

# File lib/innodb/log.rb, line 83
def block_cursor(offset)
  BufferCursor.new(block_data(offset), 0)
end
block_data(offset) click to toggle source

Get the raw byte buffer for a specific block by block offset.

# File lib/innodb/log.rb, line 75
def block_data(offset)
  raise "Invalid block offset" unless (offset % Innodb::LogBlock::BLOCK_SIZE).zero?

  @file.sysseek(offset)
  @file.sysread(Innodb::LogBlock::BLOCK_SIZE)
end
checkpoint() click to toggle source

Return the log checkpoints.

# File lib/innodb/log.rb, line 128
def checkpoint
  offset1 = LOG_HEADER_BLOCK_MAP[:LOG_CHECKPOINT_1] * Innodb::LogBlock::BLOCK_SIZE
  offset2 = LOG_HEADER_BLOCK_MAP[:LOG_CHECKPOINT_2] * Innodb::LogBlock::BLOCK_SIZE
  @checkpoint ||= CheckpointSet.new(
    checkpoint_1: block_cursor(offset1).name("checkpoint_1") { |c| read_checkpoint(c) },
    checkpoint_2: block_cursor(offset2).name("checkpoint_2") { |c| read_checkpoint(c) }
  )
end
each_block() { |block_index, current_block| ... } click to toggle source

Iterate through all log blocks, returning the block index and an InnoDB::LogBlock object for each block.

# File lib/innodb/log.rb, line 148
def each_block
  (0...@blocks).each do |block_index|
    current_block = block(block_index)
    yield block_index, current_block if current_block
  end
end
header() click to toggle source

Return the log header.

# File lib/innodb/log.rb, line 88
def header
  offset = LOG_HEADER_BLOCK_MAP[:LOG_FILE_HEADER] * Innodb::LogBlock::BLOCK_SIZE
  @header ||= block_cursor(offset).name("header") do |c|
    Header.new(
      group_id: c.name("group_id") { c.read_uint32 },
      start_lsn: c.name("start_lsn") { c.read_uint64 },
      file_no: c.name("file_no") { c.read_uint32 },
      created_by: c.name("created_by") { c.read_string(32) }
    )
  end
end
read_checkpoint(cursor) click to toggle source

Read a log checkpoint from the given cursor.

# File lib/innodb/log.rb, line 101
def read_checkpoint(cursor)
  # Log archive related fields (e.g. group_array) are not currently in
  # use or even read by InnoDB. However, for the sake of completeness,
  # they are included.
  Checkpoint.new(
    number: cursor.name("number") { cursor.read_uint64 },
    lsn: cursor.name("lsn") { cursor.read_uint64 },
    lsn_offset: cursor.name("lsn_offset") { cursor.read_uint32 },
    buffer_size: cursor.name("buffer_size") { cursor.read_uint32 },
    archived_lsn: cursor.name("archived_lsn") { cursor.read_uint64 },
    group_array:
      (0..(LOG_CHECKPOINT_GROUPS - 1)).map do |n|
        cursor.name("group_array[#{n}]") do
          CheckpointGroup.new(
            archived_file_no: cursor.name("archived_file_no") { cursor.read_uint32 },
            archived_offset: cursor.name("archived_offset") { cursor.read_uint32 }
          )
        end
      end,
    checksum_1: cursor.name("checksum_1") { cursor.read_uint32 },
    checksum_2: cursor.name("checksum_2") { cursor.read_uint32 },
    fsp_free_limit: cursor.name("fsp_free_limit") { cursor.read_uint32 },
    fsp_magic: cursor.name("fsp_magic") { cursor.read_uint32 }
  )
end