maxminddb 0.1.20 → 0.1.21

Sign up to get free protection for your applications and to get access to all the features.
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