Class: Innodb::Log
- Inherits:
-
Object
- Object
- Innodb::Log
- Defined in:
- lib/innodb/log.rb
Defined Under Namespace
Classes: Checkpoint, CheckpointGroup, CheckpointSet, Header
Constant Summary collapse
- LOG_HEADER_BLOCK_MAP =
A map of the name and position of the blocks that form the log header.
{ LOG_FILE_HEADER: 0, LOG_CHECKPOINT_1: 1, EMPTY: 2, LOG_CHECKPOINT_2: 3, }.freeze
- LOG_HEADER_BLOCKS =
Number of blocks in the log file header.
LOG_HEADER_BLOCK_MAP.size
- LOG_HEADER_SIZE =
The size in bytes of the log file header.
LOG_HEADER_BLOCKS * Innodb::LogBlock::BLOCK_SIZE
- LOG_CHECKPOINT_GROUPS =
Maximum number of log group checkpoints.
32
Instance Attribute Summary collapse
-
#blocks ⇒ Object
readonly
The number of blocks in the log.
-
#capacity ⇒ Object
readonly
The log capacity (in bytes).
-
#size ⇒ Object
readonly
The size (in bytes) of the log.
Instance Method Summary collapse
-
#block(block_index) ⇒ Object
Return a log block with a given block index as an InnoDB::LogBlock object.
-
#block_cursor(offset) ⇒ Object
Get a cursor to a block in a given offset of the log.
-
#block_data(offset) ⇒ Object
Get the raw byte buffer for a specific block by block offset.
-
#checkpoint ⇒ Object
Return the log checkpoints.
-
#each_block ⇒ Object
Iterate through all log blocks, returning the block index and an InnoDB::LogBlock object for each block.
-
#header ⇒ Object
Return the log header.
-
#initialize(filename) ⇒ Log
constructor
Open a log file.
-
#read_checkpoint(cursor) ⇒ Object
Read a log checkpoint from the given cursor.
Constructor Details
#initialize(filename) ⇒ Log
Open a log file.
58 59 60 61 62 63 |
# 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 |
Instance Attribute Details
#blocks ⇒ Object (readonly)
The number of blocks in the log.
72 73 74 |
# File 'lib/innodb/log.rb', line 72 def blocks @blocks end |
#capacity ⇒ Object (readonly)
The log capacity (in bytes).
69 70 71 |
# File 'lib/innodb/log.rb', line 69 def capacity @capacity end |
#size ⇒ Object (readonly)
The size (in bytes) of the log.
66 67 68 |
# File 'lib/innodb/log.rb', line 66 def size @size end |
Instance Method Details
#block(block_index) ⇒ Object
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.
139 140 141 142 143 144 |
# 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) ⇒ Object
Get a cursor to a block in a given offset of the log.
83 84 85 |
# File 'lib/innodb/log.rb', line 83 def block_cursor(offset) BufferCursor.new(block_data(offset), 0) end |
#block_data(offset) ⇒ Object
Get the raw byte buffer for a specific block by block offset.
75 76 77 78 79 80 |
# 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 ⇒ Object
Return the log checkpoints.
128 129 130 131 132 133 134 135 |
# 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 ⇒ Object
Iterate through all log blocks, returning the block index and an InnoDB::LogBlock object for each block.
148 149 150 151 152 153 |
# 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 ⇒ Object
Return the log header.
88 89 90 91 92 93 94 95 96 97 98 |
# 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) ⇒ Object
Read a log checkpoint from the given cursor.
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# 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 |