maxminddb 0.1.20 → 0.1.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 49781843be08dc83d3cc593d9754cdf344d270c1
4
- data.tar.gz: 5d0d83b7ba2a3cb6945db5d34fc38c579ea13a91
3
+ metadata.gz: ab8d608c0e8a6e577bdf66c0d2523c33f8d61154
4
+ data.tar.gz: 7e2ab98277eef7c50c62e8878082ac404aade464
5
5
  SHA512:
6
- metadata.gz: 7519d4cce445664ee6d1de8ad297e4cefff016971878130d71b472416167506bd484cb16decbb4bbdeaaee8bef4a6dde1908940dfee3c04b65a268ae2beebac6
7
- data.tar.gz: 0d9a52e16cb853e4139eb452f807d8aec78702b0b566d6b814560d075abe9fa856afb1fc14be1cb6ffdc839862202ad982f5e9704f50a0a26a8c35e8e5f7ad44
6
+ metadata.gz: 3c002cc49899ffa54ee320eb2c867e7b88d50e343da99a88217b5a7f0251863c1be4c8fc98c70c2038efd6362df78db1b8c2ff7ce77782d3d14fee561d2bdd75
7
+ data.tar.gz: a4888c65e1bf9bc8381f16c837f3b86cbd12f9dbf62eb840767ece6e8c18b2180cddff71c14b0630a49357635404176bf5dd9417a960c1bb6b01212c48db781d
@@ -6,6 +6,8 @@ rvm:
6
6
  - 2.2
7
7
  - 2.3
8
8
  - 2.4.0
9
+ - 2.5.1
10
+ - 2.6.0-preview2
9
11
  - jruby-19mode
10
12
 
11
13
  script: bundle exec rake
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ### 0.1.21 (July 20, 2018)
4
+
5
+ - Make the low-memory file reader opt-in
6
+
3
7
  ### 0.1.20 (July 9, 2018)
4
8
 
5
9
  - Add local_ip_alias
data/README.md CHANGED
@@ -81,10 +81,23 @@ A MaxMindDB instance doesn't do any write operation after it is created. So we c
81
81
 
82
82
  maxminddb-docker: https://github.com/samnissen/maxminddb-docker
83
83
 
84
+ ### File reading strategies
85
+
86
+ By default, `MaxMinDB.new` will read the entire database into memory. This makes subsequent lookups fast, but can result in a fairly large memory overhead.
87
+
88
+ If having a low memory overhead is important, you can use the `LowMemoryReader` by passing a `file_reader` argument to `MaxMindDB.new`. For example:
89
+
90
+ ```ruby
91
+ db = MaxMindDB.new('./GeoLite2-City.mmdb', MaxMindDB::LOW_MEMORY_FILE_READER)
92
+ ret = db.lookup('74.125.225.224')
93
+ ```
94
+
95
+ The `LowMemoryReader` will not load the entire database into memory. It's important to note that for Ruby versions lower than `2.5.0`, the `LowMemoryReader` is not process safe. Forking a process after initializing a `MaxMindDB` instance can lead to unexpected results. For Ruby versions >= `2.5.0`, `LowMemoryReader` uses `File.pread` which works safely in forking environments.
96
+
84
97
  ## Contributing
85
98
 
86
- 1. Fork it ( http://github.com/yhirose/maxminddb/fork )
87
- 2. Create your feature branch (`git checkout -b my-new-feature`)
88
- 3. Commit your changes (`git commit -am 'Add some feature'`)
89
- 4. Push to the branch (`git push origin my-new-feature`)
90
- 5. Create new Pull Request
99
+ 1. Fork it ( http://github.com/yhirose/maxminddb/fork )
100
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
101
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
102
+ 4. Push to the branch (`git push origin my-new-feature`)
103
+ 5. Create new Pull Request
@@ -5,7 +5,13 @@ require 'ipaddr'
5
5
 
6
6
  module MaxMindDB
7
7
 
8
- DEFAULT_FILE_READER = proc { |path| MaxMindDB::Reader.new(path) }
8
+ # The default reader for MaxMindDB files. Reads the database into memory.
9
+ # This creates a higher memory overhead, but faster lookup times.
10
+ DEFAULT_FILE_READER = proc { |path| File.binread(path) }
11
+
12
+ # A low memory file reader for MaxMindDB files. Avoids reading the database
13
+ # into memory. Has a lower memory footprint but slower lookup times.
14
+ LOW_MEMORY_FILE_READER = proc { |path| MaxMindDB::LowMemoryReader.new(path) }
9
15
 
10
16
  def self.new(path, file_reader=DEFAULT_FILE_READER)
11
17
  Client.new(path, file_reader)
@@ -1,6 +1,8 @@
1
1
 
2
+ require 'thread'
3
+
2
4
  module MaxMindDB
3
- class Reader
5
+ class LowMemoryReader
4
6
  METADATA_MAX_SIZE = 128 * 1024
5
7
 
6
8
  def initialize(path)
@@ -21,9 +23,15 @@ module MaxMindDB
21
23
  end
22
24
 
23
25
  def atomic_read(length, pos)
24
- @mutex.synchronize do
25
- @file.seek(pos)
26
- @file.read(length)
26
+ # Prefer `pread` in environments where it is available. `pread` provides
27
+ # atomic file access across processes.
28
+ if @file.respond_to?(:pread)
29
+ @file.pread(length, pos)
30
+ else
31
+ @mutex.synchronize do
32
+ @file.seek(pos)
33
+ @file.read(length)
34
+ end
27
35
  end
28
36
  end
29
37
  end
@@ -1,3 +1,3 @@
1
1
  module MaxMindDB
2
- VERSION = "0.1.20"
2
+ VERSION = "0.1.21"
3
3
  end
@@ -1,215 +1,224 @@
1
1
  require 'maxminddb'
2
2
 
3
3
  describe MaxMindDB do
4
- let(:city_db) { MaxMindDB.new('spec/cache/GeoLite2-City.mmdb') }
5
- let(:country_db) { MaxMindDB.new('spec/cache/GeoLite2-Country.mmdb') }
6
- let(:rec32_db) { MaxMindDB.new('spec/data/32bit_record_data.mmdb') }
4
+ [
5
+ ['default file reader', MaxMindDB::DEFAULT_FILE_READER],
6
+ ['low memory file reader', MaxMindDB::LOW_MEMORY_FILE_READER],
7
+ ].each do |file_reader|
8
+ description, reader = file_reader
7
9
 
8
- context 'for the ip 74.125.225.224' do
9
- let(:ip) { '74.125.225.224' }
10
+ describe description do
11
+ let(:city_db) { MaxMindDB.new('spec/cache/GeoLite2-City.mmdb', reader) }
12
+ let(:country_db) { MaxMindDB.new('spec/cache/GeoLite2-Country.mmdb', reader) }
13
+ let(:rec32_db) { MaxMindDB.new('spec/data/32bit_record_data.mmdb', reader) }
10
14
 
11
- it 'returns a MaxMindDB::Result' do
12
- expect(city_db.lookup(ip)).to be_kind_of(MaxMindDB::Result)
13
- end
15
+ context 'for the ip 74.125.225.224' do
16
+ let(:ip) { '74.125.225.224' }
14
17
 
15
- it 'finds data' do
16
- expect(city_db.lookup(ip)).to be_found
17
- end
18
+ it 'returns a MaxMindDB::Result' do
19
+ expect(city_db.lookup(ip)).to be_kind_of(MaxMindDB::Result)
20
+ end
18
21
 
19
- it 'returns Mountain View as the English name' do
20
- expect(city_db.lookup(ip).city.name).to eq('Alameda')
21
- end
22
+ it 'finds data' do
23
+ expect(city_db.lookup(ip)).to be_found
24
+ end
22
25
 
23
- it 'returns -122.0574 as the longitude' do
24
- expect(city_db.lookup(ip).location.longitude).to eq(-122.2788)
25
- end
26
+ it 'returns Mountain View as the English name' do
27
+ expect(city_db.lookup(ip).city.name).to eq('Alameda')
28
+ end
26
29
 
27
- it 'returns nil for is_anonymous_proxy' do
28
- expect(city_db.lookup(ip).traits.is_anonymous_proxy).to eq(nil)
29
- end
30
+ it 'returns -122.0574 as the longitude' do
31
+ expect(city_db.lookup(ip).location.longitude).to eq(-122.2788)
32
+ end
30
33
 
31
- it 'returns United States as the English country name' do
32
- expect(country_db.lookup(ip).country.name).to eq('United States')
33
- end
34
+ it 'returns nil for is_anonymous_proxy' do
35
+ expect(city_db.lookup(ip).traits.is_anonymous_proxy).to eq(nil)
36
+ end
34
37
 
35
- it 'returns false for the is_in_european_union' do
36
- expect(country_db.lookup(ip).country.is_in_european_union).to eq(nil)
37
- end
38
+ it 'returns United States as the English country name' do
39
+ expect(country_db.lookup(ip).country.name).to eq('United States')
40
+ end
38
41
 
39
- it 'returns US as the country iso code' do
40
- expect(country_db.lookup(ip).country.iso_code).to eq('US')
41
- end
42
+ it 'returns false for the is_in_european_union' do
43
+ expect(country_db.lookup(ip).country.is_in_european_union).to eq(nil)
44
+ end
42
45
 
43
- context 'as a Integer' do
44
- let(:integer_ip) { IPAddr.new(ip).to_i }
46
+ it 'returns US as the country iso code' do
47
+ expect(country_db.lookup(ip).country.iso_code).to eq('US')
48
+ end
45
49
 
46
- it 'returns a MaxMindDB::Result' do
47
- expect(city_db.lookup(integer_ip)).to be_kind_of(MaxMindDB::Result)
48
- end
50
+ context 'as a Integer' do
51
+ let(:integer_ip) { IPAddr.new(ip).to_i }
49
52
 
50
- it 'returns Mountain View as the English name' do
51
- expect(city_db.lookup(integer_ip).city.name).to eq('Alameda')
52
- end
53
+ it 'returns a MaxMindDB::Result' do
54
+ expect(city_db.lookup(integer_ip)).to be_kind_of(MaxMindDB::Result)
55
+ end
56
+
57
+ it 'returns Mountain View as the English name' do
58
+ expect(city_db.lookup(integer_ip).city.name).to eq('Alameda')
59
+ end
53
60
 
54
- it 'returns United States as the English country name' do
55
- expect(country_db.lookup(integer_ip).country.name).to eq('United States')
61
+ it 'returns United States as the English country name' do
62
+ expect(country_db.lookup(integer_ip).country.name).to eq('United States')
63
+ end
64
+ end
56
65
  end
57
- end
58
- end
59
66
 
60
- context 'for the ip 2001:708:510:8:9a6:442c:f8e0:7133' do
61
- let(:ip) { '2001:708:510:8:9a6:442c:f8e0:7133' }
67
+ context 'for the ip 2001:708:510:8:9a6:442c:f8e0:7133' do
68
+ let(:ip) { '2001:708:510:8:9a6:442c:f8e0:7133' }
62
69
 
63
- it 'finds data' do
64
- expect(city_db.lookup(ip)).to be_found
65
- end
70
+ it 'finds data' do
71
+ expect(city_db.lookup(ip)).to be_found
72
+ end
66
73
 
67
- it 'returns true for the is_in_european_union' do
68
- expect(country_db.lookup(ip).country.is_in_european_union).to eq(true)
69
- end
74
+ it 'returns true for the is_in_european_union' do
75
+ expect(country_db.lookup(ip).country.is_in_european_union).to eq(true)
76
+ end
70
77
 
71
- it 'returns FI as the country iso code' do
72
- expect(country_db.lookup(ip).country.iso_code).to eq('FI')
73
- end
78
+ it 'returns FI as the country iso code' do
79
+ expect(country_db.lookup(ip).country.iso_code).to eq('FI')
80
+ end
74
81
 
75
- context 'as an integer' do
76
- let(:integer_ip) { IPAddr.new(ip).to_i }
82
+ context 'as an integer' do
83
+ let(:integer_ip) { IPAddr.new(ip).to_i }
77
84
 
78
- it 'returns FI as the country iso code' do
79
- expect(country_db.lookup(integer_ip).country.iso_code).to eq('FI')
85
+ it 'returns FI as the country iso code' do
86
+ expect(country_db.lookup(integer_ip).country.iso_code).to eq('FI')
87
+ end
88
+ end
80
89
  end
81
- end
82
- end
83
90
 
84
- context 'for a Canadian ipv6' do
85
- let(:ip) { '2607:5300:60:72ba::' }
91
+ context 'for a Canadian ipv6' do
92
+ let(:ip) { '2607:5300:60:72ba::' }
86
93
 
87
- it 'finds data' do
88
- expect(city_db.lookup(ip)).to be_found
89
- end
94
+ it 'finds data' do
95
+ expect(city_db.lookup(ip)).to be_found
96
+ end
90
97
 
91
- it 'returns true for the is_in_european_union' do
92
- expect(country_db.lookup(ip).country.is_in_european_union).to be_falsey
93
- end
98
+ it 'returns true for the is_in_european_union' do
99
+ expect(country_db.lookup(ip).country.is_in_european_union).to be_falsey
100
+ end
94
101
 
95
- it 'returns CA as the country iso code' do
96
- expect(country_db.lookup(ip).country.iso_code).to eq('CA')
97
- end
98
- end
102
+ it 'returns CA as the country iso code' do
103
+ expect(country_db.lookup(ip).country.iso_code).to eq('CA')
104
+ end
105
+ end
99
106
 
100
- context 'for a German IPv6' do
101
- let(:ip) { '2a01:488:66:1000:2ea3:495e::1' }
107
+ context 'for a German IPv6' do
108
+ let(:ip) { '2a01:488:66:1000:2ea3:495e::1' }
102
109
 
103
- it 'finds data' do
104
- expect(city_db.lookup(ip)).to be_found
105
- end
110
+ it 'finds data' do
111
+ expect(city_db.lookup(ip)).to be_found
112
+ end
106
113
 
107
- it 'returns false for the is_in_european_union' do
108
- expect(country_db.lookup(ip).country.is_in_european_union).to eq(true)
109
- end
114
+ it 'returns true for the is_in_european_union' do
115
+ expect(country_db.lookup(ip).country.is_in_european_union).to eq(true)
116
+ end
110
117
 
111
- it 'returns DE as the country iso code' do
112
- expect(country_db.lookup(ip).country.iso_code).to eq('DE')
113
- end
114
- end
118
+ it 'returns DE as the country iso code' do
119
+ expect(country_db.lookup(ip).country.iso_code).to eq('DE')
120
+ end
121
+ end
115
122
 
116
- context 'for the ip 127.0.0.1' do
117
- let(:ip) { '127.0.0.1' }
123
+ context 'for the ip 127.0.0.1' do
124
+ let(:ip) { '127.0.0.1' }
118
125
 
119
- it 'returns a MaxMindDB::Result' do
120
- expect(city_db.lookup(ip)).to be_kind_of(MaxMindDB::Result)
121
- end
126
+ it 'returns a MaxMindDB::Result' do
127
+ expect(city_db.lookup(ip)).to be_kind_of(MaxMindDB::Result)
128
+ end
122
129
 
123
- it "doesn't find data" do
124
- expect(city_db.lookup(ip)).to_not be_found
125
- end
126
- end
130
+ it "doesn't find data" do
131
+ expect(city_db.lookup(ip)).to_not be_found
132
+ end
133
+ end
127
134
 
128
- context 'for local ip addresses' do
129
- let(:ip) { '127.0.0.1' }
135
+ context 'for local ip addresses' do
136
+ let(:ip) { '127.0.0.1' }
130
137
 
131
- context 'for city_db' do
132
- before do
133
- city_db.local_ip_alias = '74.125.225.224'
134
- end
138
+ context 'for city_db' do
139
+ before do
140
+ city_db.local_ip_alias = '74.125.225.224'
141
+ end
135
142
 
136
- it 'returns a MaxMindDB::Result' do
137
- expect(city_db.lookup(ip)).to be_kind_of(MaxMindDB::Result)
138
- end
143
+ it 'returns a MaxMindDB::Result' do
144
+ expect(city_db.lookup(ip)).to be_kind_of(MaxMindDB::Result)
145
+ end
139
146
 
140
- it 'finds data' do
141
- expect(city_db.lookup(ip)).to be_found
142
- end
147
+ it 'finds data' do
148
+ expect(city_db.lookup(ip)).to be_found
149
+ end
143
150
 
144
- it 'returns Mountain View as the English name' do
145
- expect(city_db.lookup(ip).city.name).to eq('Alameda')
146
- end
151
+ it 'returns Mountain View as the English name' do
152
+ expect(city_db.lookup(ip).city.name).to eq('Alameda')
153
+ end
147
154
 
148
- it 'returns -122.0574 as the longitude' do
149
- expect(city_db.lookup(ip).location.longitude).to eq(-122.2788)
150
- end
155
+ it 'returns -122.0574 as the longitude' do
156
+ expect(city_db.lookup(ip).location.longitude).to eq(-122.2788)
157
+ end
151
158
 
152
- it 'returns nil for is_anonymous_proxy' do
153
- expect(city_db.lookup(ip).traits.is_anonymous_proxy).to eq(nil)
154
- end
155
- end
159
+ it 'returns nil for is_anonymous_proxy' do
160
+ expect(city_db.lookup(ip).traits.is_anonymous_proxy).to eq(nil)
161
+ end
162
+ end
156
163
 
157
- context 'for country_db' do
158
- before do
159
- country_db.local_ip_alias = '74.125.225.224'
160
- end
164
+ context 'for country_db' do
165
+ before do
166
+ country_db.local_ip_alias = '74.125.225.224'
167
+ end
161
168
 
162
- it 'returns United States as the English country name' do
163
- expect(country_db.lookup(ip).country.name).to eq('United States')
164
- end
169
+ it 'returns United States as the English country name' do
170
+ expect(country_db.lookup(ip).country.name).to eq('United States')
171
+ end
165
172
 
166
- it 'returns false for the is_in_european_union' do
167
- expect(country_db.lookup(ip).country.is_in_european_union).to eq(nil)
168
- end
173
+ it 'returns false for the is_in_european_union' do
174
+ expect(country_db.lookup(ip).country.is_in_european_union).to eq(nil)
175
+ end
169
176
 
170
- it 'returns US as the country iso code' do
171
- expect(country_db.lookup(ip).country.iso_code).to eq('US')
177
+ it 'returns US as the country iso code' do
178
+ expect(country_db.lookup(ip).country.iso_code).to eq('US')
179
+ end
180
+ end
172
181
  end
173
- end
174
- end
175
182
 
176
- context 'for 32bit record data' do
177
- let(:ip) { '1.0.16.1' }
178
-
179
- it 'finds data' do
180
- expect(rec32_db.lookup(ip)).to be_found
181
- end
182
- end
183
+ context 'for 32bit record data' do
184
+ let(:ip) { '1.0.16.1' }
183
185
 
184
- context 'test ips' do
185
- [
186
- ['185.23.124.1', 'SA'],
187
- ['178.72.254.1', 'CZ'],
188
- ['95.153.177.210', 'RU'],
189
- ['200.148.105.119', 'BR'],
190
- ['195.59.71.43', 'GB'],
191
- ['179.175.47.87', 'BR'],
192
- ['202.67.40.50', 'ID'],
193
- ].each do |ip, iso|
194
- it 'returns a MaxMindDB::Result' do
195
- expect(city_db.lookup(ip)).to be_kind_of(MaxMindDB::Result)
186
+ it 'finds data' do
187
+ expect(rec32_db.lookup(ip)).to be_found
188
+ end
196
189
  end
197
190
 
198
- it "returns #{iso} as the country iso code" do
199
- expect(country_db.lookup(ip).country.iso_code).to eq(iso)
191
+ context 'test ips' do
192
+ [
193
+ ['185.23.124.1', 'SA'],
194
+ ['178.72.254.1', 'CZ'],
195
+ ['95.153.177.210', 'RU'],
196
+ ['200.148.105.119', 'BR'],
197
+ ['195.59.71.43', 'GB'],
198
+ ['179.175.47.87', 'BR'],
199
+ ['202.67.40.50', 'ID'],
200
+ ].each do |ip, iso|
201
+ it 'returns a MaxMindDB::Result' do
202
+ expect(city_db.lookup(ip)).to be_kind_of(MaxMindDB::Result)
203
+ end
204
+
205
+ it "returns #{iso} as the country iso code" do
206
+ expect(country_db.lookup(ip).country.iso_code).to eq(iso)
207
+ end
208
+ end
200
209
  end
201
- end
202
- end
203
210
 
204
- context 'test boolean data' do
205
- let(:ip) { '41.194.0.1' }
211
+ context 'test boolean data' do
212
+ let(:ip) { '41.194.0.1' }
206
213
 
207
- it 'returns true for the is_satellite_provider trait' do
208
- expect(city_db.lookup(ip).traits.is_satellite_provider).to eq(nil)
209
- end
214
+ it 'returns true for the is_satellite_provider trait' do
215
+ expect(city_db.lookup(ip).traits.is_satellite_provider).to eq(nil)
216
+ end
210
217
 
211
- # There are no false booleans in the database that we can test.
212
- # False values are simply omitted.
218
+ # There are no false booleans in the database that we can test.
219
+ # False values are simply omitted.
220
+ end
221
+ end
213
222
  end
214
223
  end
215
224
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: maxminddb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.20
4
+ version: 0.1.21
5
5
  platform: ruby
6
6
  authors:
7
7
  - yhirose
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-07-09 00:00:00.000000000 Z
11
+ date: 2018-07-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler