Class: Innodb::Space

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

Overview

An InnoDB tablespace file, which can be either a multi-table ibdataN file or a single-table “innodb_file_per_table” .ibd file.

Constant Summary collapse

DEFAULT_PAGE_SIZE =

InnoDB’s default page size is 16KiB.

16384

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(file, page_size = DEFAULT_PAGE_SIZE) ⇒ Space

Open a tablespace file, providing the page size to use. Pages that aren’t 16 KiB may not be supported well.



9
10
11
12
13
14
15
# File 'lib/innodb/space.rb', line 9

def initialize(file, page_size=DEFAULT_PAGE_SIZE)
  @file = File.open(file)
  @page_size = page_size
  @size = @file.stat.size
  @pages = (@size / page_size)
  @record_describer = nil
end

Instance Attribute Details

#page_sizeObject (readonly)

The size (in bytes) of each page in the space.



22
23
24
# File 'lib/innodb/space.rb', line 22

def page_size
  @page_size
end

#pagesObject (readonly)

The number of pages in the space.



28
29
30
# File 'lib/innodb/space.rb', line 28

def pages
  @pages
end

#record_describerObject

An object which can be used to describe records found in pages within this space.



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

def record_describer
  @record_describer
end

#sizeObject (readonly)

The size (in bytes) of the space



25
26
27
# File 'lib/innodb/space.rb', line 25

def size
  @size
end

Instance Method Details

#each_indexObject

Iterate through each index by guessing that the root pages will be present starting at page 3, and walking forward until we find a non- root page. This should work fine for IBD files, but not for ibdata files.



70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/innodb/space.rb', line 70

def each_index
  unless block_given?
    return enum_for(:each_index)
  end

  (3...@pages).each do |page_number|
    page = page(page_number)
    if page.type == :INDEX && page.root?
      yield index(page_number)
    else
      break
    end
  end
end

#each_page(start_page = 0) ⇒ Object

Iterate through all pages in a tablespace, returning the page number and an Innodb::Page object for each one.



87
88
89
90
91
92
93
94
95
96
# File 'lib/innodb/space.rb', line 87

def each_page(start_page=0)
  unless block_given?
    return enum_for(:each_page)
  end

  (start_page...@pages).each do |page_number|
    current_page = page(page_number)
    yield page_number, current_page if current_page
  end
end

#each_page_type_region(start_page = 0) {|region| ... } ⇒ Object

Iterate through unique regions in the space by page type. This is useful to achieve an overall view of the space.

Yields:

  • (region)


100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/innodb/space.rb', line 100

def each_page_type_region(start_page=0)
  unless block_given?
    return enum_for(:each_page_type_region)
  end

  region = nil
  each_page(start_page) do |page_number, page|
    if region && region[:type] == page.type
      region[:end] = page_number
      region[:count] += 1
    else
      yield region if region
      region = {
        :start => page_number,
        :end   => page_number,
        :type  => page.type,
        :count => 1,
      }
    end
  end
  yield region if region
end

#extent_sizeObject

The size (in bytes) of an extent.



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

def extent_size
  page_size * pages_per_extent
end

#index(root_page_number) ⇒ Object

Get an Innodb::Index object for a specific index by root page number.



62
63
64
# File 'lib/innodb/space.rb', line 62

def index(root_page_number)
  Innodb::Index.new(self, root_page_number)
end

#list(name) ⇒ Object

Get an Innodb::List object for a specific list by list name.



57
58
59
# File 'lib/innodb/space.rb', line 57

def list(name)
  page(0).fsp_header[name]
end

#page(page_number) ⇒ Object

Get an Innodb::Page object for a specific page by page number.



41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/innodb/space.rb', line 41

def page(page_number)
  offset = page_number.to_i * page_size
  return nil unless offset < @size
  return nil unless (offset + page_size) <= @size
  @file.seek(offset)
  page_data = @file.read(page_size)
  this_page = Innodb::Page.parse(self, page_data)

  if this_page.type == :INDEX
    this_page.record_describer = @record_describer
  end

  this_page
end

#pages_per_extentObject

The number of pages per extent.



31
32
33
# File 'lib/innodb/space.rb', line 31

def pages_per_extent
  64
end