Class: MaxMind::DB

Inherits:
Object
  • Object
show all
Defined in:
lib/maxmind/db.rb,
lib/maxmind/db/errors.rb,
lib/maxmind/db/decoder.rb,
lib/maxmind/db/metadata.rb,
lib/maxmind/db/file_reader.rb,
lib/maxmind/db/memory_reader.rb

Overview

DB provides a way to read MaxMind DB files.

MaxMind DB is a binary file format that stores data indexed by IP address subnets (IPv4 or IPv6).

This class is a pure Ruby implementation of a reader for the format.

Example

require 'maxmind/db'

reader = MaxMind::DB.new('GeoIP2-City.mmdb', mode: MaxMind::DB::MODE_MEMORY)

record = reader.get('1.1.1.1')
if record.nil?
  puts '1.1.1.1 was not found in the database'
else
  puts record['country']['iso_code']
  puts record['country']['names']['en']
end

reader.close

Defined Under Namespace

Classes: InvalidDatabaseError, Metadata

Constant Summary collapse

MODE_AUTO =

Choose the default method to open the database. Currently the default is MODE_FILE.

:MODE_AUTO
MODE_FILE =

Open the database as a regular file and read on demand.

:MODE_FILE
MODE_MEMORY =

Read the database into memory. This is faster than MODE_FILE but causes increased memory use.

:MODE_MEMORY

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(database, options = {}) ⇒ DB

Create a DB. A DB provides a way to read MaxMind DB files. If you’re performing multiple lookups, it’s most efficient to create one DB and reuse it.

Once created, the DB is safe to use for lookups from multiple threads. It is safe to use after forking only if you use MODE_MEMORY or if your version of Ruby supports IO#pread.

Parameters:

  • database (String)

    a path to a MaxMind DB.

  • options (Hash<Symbol, Symbol>) (defaults to: {})

    options controlling the behavior of the DB.

Options Hash (options):

  • :mode (Symbol)

    Defines how to open the database. It may be one of MODE_AUTO, MODE_FILE, or MODE_MEMORY. If you don’t provide one, DB uses MODE_AUTO. Refer to the definition of those constants for an explanation of their meaning.

Raises:

  • (InvalidDatabaseError)

    if the database is corrupt or invalid.

  • (ArgumentError)

    if the mode is invalid.



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
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/maxmind/db.rb', line 86

def initialize(database, options = {})
  options[:mode] = MODE_AUTO unless options.key?(:mode)

  case options[:mode]
  when MODE_AUTO, MODE_FILE
    @io = FileReader.new(database)
  when MODE_MEMORY
    @io = MemoryReader.new(database)
  when MODE_PARAM_IS_BUFFER
    @io = MemoryReader.new(database, is_buffer: true)
  else
    raise ArgumentError, 'Invalid mode'
  end

  begin
    @size = @io.size

     = 
     = Decoder.new(@io, )
    , = .decode()
    @metadata = Metadata.new()
    @decoder = Decoder.new(@io, @metadata.search_tree_size +
                           DATA_SECTION_SEPARATOR_SIZE)

    # Store copies as instance variables to reduce method calls.
    @ip_version       = @metadata.ip_version
    @node_count       = @metadata.node_count
    @node_byte_size   = @metadata.node_byte_size
    @record_size      = @metadata.record_size
    @search_tree_size = @metadata.search_tree_size

    @ipv4_start = nil
    # Find @ipv4_start up front. If we don't, we either have a race to
    # get/set it or have to synchronize access.
    start_node(0)
  rescue StandardError => e
    @io.close
    raise e
  end
end

Instance Attribute Details

#metadataMaxMind::DB::Metadata (readonly)

Return the metadata associated with the MaxMind DB



62
63
64
# File 'lib/maxmind/db.rb', line 62

def 
  @metadata
end

Instance Method Details

#closevoid

This method returns an undefined value.

Close the DB and return resources to the system.



298
299
300
# File 'lib/maxmind/db.rb', line 298

def close
  @io.close
end

#get(ip_address) ⇒ Object?

Return the record for the IP address in the MaxMind DB. The record can be one of several types and depends on the contents of the database.

If no record is found for the IP address, get returns nil.

Parameters:

  • ip_address (String, IPAddr)

    IPv4 or IPv6 address.

Returns:

  • (Object, nil)

Raises:

  • (ArgumentError)

    if you attempt to look up an IPv6 address in an IPv4-only database.

  • (InvalidDatabaseError)

    if the database is corrupt or invalid.



141
142
143
144
145
# File 'lib/maxmind/db.rb', line 141

def get(ip_address)
  record, = get_with_prefix_length(ip_address)

  record
end

#get_with_prefix_length(ip_address) ⇒ Array<(Object, Integer)>

Return an array containing the record for the IP address in the MaxMind DB and its associated network prefix length. The record can be one of several types and depends on the contents of the database.

If no record is found for the IP address, the record will be nil and the prefix length will be the value for the missing network.

Parameters:

  • ip_address (String, IPAddr)

    IPv4 or IPv6 address.

Returns:

  • (Array<(Object, Integer)>)

Raises:

  • (ArgumentError)

    if you attempt to look up an IPv6 address in an IPv4-only database.

  • (InvalidDatabaseError)

    if the database is corrupt or invalid.



163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/maxmind/db.rb', line 163

def get_with_prefix_length(ip_address)
  ip = ip_address.is_a?(IPAddr) ? ip_address : IPAddr.new(ip_address)

  # We could check the IP has the correct prefix (32 or 128) but I do not
  # for performance reasons.

  ip_version = ip.ipv6? ? 6 : 4
  if ip_version == 6 && @ip_version == 4
    raise ArgumentError,
          "Error looking up #{ip}. You attempted to look up an IPv6 address in an IPv4-only database."
  end

  pointer, depth = find_address_in_tree(ip, ip_version)
  return nil, depth if pointer == 0

  [resolve_data_pointer(pointer), depth]
end