Class: Innodb::System

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

Overview

A class representing an entire InnoDB system, having a system tablespace and any number of attached single-table tablespaces.

Constant Summary collapse

SYSTEM_SPACE_ID =

The space ID of the system space, always 0.

0

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(arg) ⇒ System

Returns a new instance of System.



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/innodb/system.rb', line 21

def initialize(arg)
  if arg.is_a?(Array) && arg.size > 1
    data_filenames = arg
  else
    arg = arg.first if arg.is_a?(Array)
    if File.directory?(arg)
      data_filenames = Dir.glob(arg + "/ibdata?").sort
      if data_filenames.empty?
        raise "Couldn't find any ibdata files in #{arg}"
      end
    else
      data_filenames = [arg]
    end
  end

  @spaces = {}
  @orphans = []
  @config = {
    :datadir => File.dirname(data_filenames.first),
  }

  add_space_file(data_filenames)

  @data_dictionary = Innodb::DataDictionary.new(system_space)
end

Instance Attribute Details

#configObject (readonly)

A hash of configuration options by configuration key.



7
8
9
# File 'lib/innodb/system.rb', line 7

def config
  @config
end

#data_dictionaryObject (readonly)

The Innodb::DataDictionary for this system.



16
17
18
# File 'lib/innodb/system.rb', line 16

def data_dictionary
  @data_dictionary
end

#orphansObject (readonly)

Array of space names for which a space file was not found.



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

def orphans
  @orphans
end

#spacesObject (readonly)

A hash of spaces by space ID.



10
11
12
# File 'lib/innodb/system.rb', line 10

def spaces
  @spaces
end

Instance Method Details

#add_space(space) ⇒ Object

Add an already-constructed Innodb::Space object.



53
54
55
56
57
58
59
# File 'lib/innodb/system.rb', line 53

def add_space(space)
  unless space.is_a?(Innodb::Space)
    raise "Object was not an Innodb::Space"
  end

  spaces[space.space_id.to_i] = space
end

#add_space_file(space_filenames) ⇒ Object

Add a space by filename.



62
63
64
65
66
# File 'lib/innodb/system.rb', line 62

def add_space_file(space_filenames)
  space = Innodb::Space.new(space_filenames)
  space.innodb_system = self
  add_space(space)
end

#add_space_orphan(space_file) ⇒ Object

Add an orphaned space.



69
70
71
# File 'lib/innodb/system.rb', line 69

def add_space_orphan(space_file)
  orphans << space_file
end

#add_table(table_name) ⇒ Object

Add a space by table name, constructing an appropriate filename from the provided table name.



75
76
77
78
79
80
81
82
# File 'lib/innodb/system.rb', line 75

def add_table(table_name)
  space_file = "%s/%s.ibd" % [config[:datadir], table_name]
  if File.exist?(space_file)
    add_space_file(space_file)
  else
    add_space_orphan(table_name)
  end
end

#clustered_index_by_table_id(table_id) ⇒ Object

Return the clustered index given a table ID.



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

def clustered_index_by_table_id(table_id)
  if table_name = table_name_by_id(table_id)
    index_by_name(table_name, clustered_index_by_table_name(table_name))
  end
end

#clustered_index_by_table_name(table_name) ⇒ Object

Return the clustered index name given a table name.



193
194
195
# File 'lib/innodb/system.rb', line 193

def clustered_index_by_table_name(table_name)
  data_dictionary.clustered_index_name_by_table_name(table_name)
end

#each_column_name_by_table_name(table_name) ⇒ Object

Iterate through all column names by table name.



138
139
140
141
142
143
144
145
146
147
148
# File 'lib/innodb/system.rb', line 138

def each_column_name_by_table_name(table_name)
  unless block_given?
    return enum_for(:each_column_name_by_table_name, table_name)
  end

  data_dictionary.each_column_by_table_name(table_name) do |record|
    yield record["NAME"]
  end

  nil
end

#each_index_field_name_by_index_name(table_name, index_name) ⇒ Object

Iterate through all field names in a given index by table name and index name.



165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/innodb/system.rb', line 165

def each_index_field_name_by_index_name(table_name, index_name)
  unless block_given?
    return enum_for(:each_index_field_name_by_index_name,
                    table_name, index_name)
  end

  data_dictionary.each_field_by_index_name(table_name, index_name) do |record|
    yield record["COL_NAME"]
  end

  nil
end

#each_index_name_by_table_name(table_name) ⇒ Object

Iterate through all index names by table name.



151
152
153
154
155
156
157
158
159
160
161
# File 'lib/innodb/system.rb', line 151

def each_index_name_by_table_name(table_name)
  unless block_given?
    return enum_for(:each_index_name_by_table_name, table_name)
  end

  data_dictionary.each_index_by_table_name(table_name) do |record|
    yield record["NAME"]
  end

  nil
end

#each_orphanObject

Iterate throught all orphaned spaces.



125
126
127
128
129
130
131
132
133
134
135
# File 'lib/innodb/system.rb', line 125

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

  orphans.each do |space_name|
    yield space_name
  end

  nil
end

#each_table_nameObject

Iterate through all table names.



112
113
114
115
116
117
118
119
120
121
122
# File 'lib/innodb/system.rb', line 112

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

  data_dictionary.each_table do |record|
    yield record["NAME"]
  end

  nil
end

#historyObject



227
228
229
# File 'lib/innodb/system.rb', line 227

def history
  Innodb::History.new(self)
end

#index_by_name(table_name, index_name) ⇒ Object

Return an Innodb::Index object given a table name and index name.



210
211
212
213
214
215
216
217
218
# File 'lib/innodb/system.rb', line 210

def index_by_name(table_name, index_name)
  index_record = data_dictionary.index_by_name(table_name, index_name)

  index_space = space(index_record["SPACE"])
  describer = data_dictionary.record_describer_by_index_name(table_name, index_name)
  index = index_space.index(index_record["PAGE_NO"], describer)

  index
end

#index_name_by_id(index_id) ⇒ Object

Return the index name given an index ID.



186
187
188
189
190
# File 'lib/innodb/system.rb', line 186

def index_name_by_id(index_id)
  if index_record = data_dictionary.index_by_id(index_id)
    index_record["NAME"]
  end
end

#space(space_id) ⇒ Object

Return an Innodb::Space object for a given space ID, looking up and adding the single-table space if necessary.



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

def space(space_id)
  return spaces[space_id] if spaces[space_id]

  unless table_record = data_dictionary.table_by_space_id(space_id)
    raise "Table with space ID #{space_id} not found"
  end

  add_table(table_record["NAME"])

  spaces[space_id]
end

#space_by_table_name(table_name) ⇒ Object

Return an Innodb::Space object by table name.



99
100
101
102
103
104
105
106
107
108
109
# File 'lib/innodb/system.rb', line 99

def space_by_table_name(table_name)
  unless table_record = data_dictionary.table_by_name(table_name)
    raise "Table #{table_name} not found"
  end

  if table_record["SPACE"] == 0
    return nil
  end

  space(table_record["SPACE"])
end

#system_spaceObject

A helper to get the system space.



48
49
50
# File 'lib/innodb/system.rb', line 48

def system_space
  spaces[SYSTEM_SPACE_ID]
end

#table_and_index_name_by_id(index_id) ⇒ Object

Return an array of the table name and index name given an index ID.



198
199
200
201
202
203
204
205
206
207
# File 'lib/innodb/system.rb', line 198

def table_and_index_name_by_id(index_id)
  if dd_index = data_dictionary.data_dictionary_index_ids[index_id]
    # This is a data dictionary index, which won't be found in the data
    # dictionary itself.
    [dd_index[:table], dd_index[:index]]
  elsif index_record = data_dictionary.index_by_id(index_id)
    # This is a system or user index.
    [table_name_by_id(index_record["TABLE_ID"]), index_record["NAME"]]
  end
end

#table_name_by_id(table_id) ⇒ Object

Return the table name given a table ID.



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

def table_name_by_id(table_id)
  if table_record = data_dictionary.table_by_id(table_id)
    table_record["NAME"]
  end
end