geoip2 0.1.0.3 → 0.1.0.4
raw patch · 6 files changed
+25/−39 lines, 6 filesdep +cerealdep −binarydep −lrucachePVP ok
version bump matches the API change (PVP)
Dependencies added: cereal
Dependencies removed: binary, lrucache
API changes (from Hackage documentation)
Files
- ChangeLog.md +5/−1
- Data/GeoIP2.hs +6/−22
- Data/GeoIP2/Fields.hs +7/−8
- Data/GeoIP2/SearchTree.hs +4/−4
- README.md +1/−1
- geoip2.cabal +2/−3
ChangeLog.md view
@@ -1,9 +1,13 @@+# 0.1.0.3 -> 0.1.0.4+- Removed lru+- Switched from binary to cereal with a significant speedup+ # 0.1.0.2 -> 0.1.0.3 - Changed bytestring-mmap to mmap - Add LRU caching to improve performance (10000 entries are cached) # 0.1.0.1 -> 0.1.0.2- + - GHC-7.10 compatibiliy - Add Changelog.md - List Changelog.md and README.md in cabal's extra-source-files
Data/GeoIP2.hs view
@@ -25,17 +25,14 @@ import Control.Applicative ((<$>), (<*>)) import Control.Monad (unless, when)-import Data.Binary+import Data.Serialize import qualified Data.ByteString as BS-import qualified Data.ByteString.Lazy as BL-import qualified Data.Cache.LRU.IO as LRU import Data.Int import Data.IP (IP (..), ipv4ToIPv6) import qualified Data.Map as Map import Data.Maybe (fromMaybe, mapMaybe) import qualified Data.Text as T import System.IO.MMap-import System.IO.Unsafe (unsafePerformIO) import Data.GeoIP2.Fields import Data.GeoIP2.SearchTree@@ -46,7 +43,6 @@ -- | Handle for search operations data GeoDB = GeoDB { geoMem :: BS.ByteString- , geoLru :: LRU.AtomicLRU Int GeoField , geoDbType :: T.Text -- ^ String that indicates the structure of each data record associated with an IP address , geoDbLanguages :: [T.Text] -- ^ Languages supported in database , geoDbNodeCount :: Int64@@ -67,11 +63,10 @@ openGeoDB :: FilePath -> IO GeoDB openGeoDB geoFile = do bsmem <- mmapFileByteString geoFile Nothing- let (DataMap hdr) = decode (BL.fromStrict $ getHeaderBytes bsmem)+ let (Right (DataMap hdr)) = decode (getHeaderBytes bsmem) when (hdr .: "binary_format_major_version" /= (2 :: Int)) $ error "Unsupported database version, only v2 supported." unless (hdr .: "record_size" `elem` [24, 28, 32 :: Int]) $ error "Record size not supported."- lru <- LRU.newAtomicLRU (Just 10000)- return $ GeoDB bsmem lru (hdr .: "database_type")+ return $ GeoDB bsmem (hdr .: "database_type") (fromMaybe [] $ hdr .:? "languages") (hdr .: "node_count") (hdr .: "record_size") (if (hdr .: "ip_version") == (4 :: Int) then GeoIPv4 else GeoIPv6)@@ -88,20 +83,9 @@ where dataSectionStart = (geoDbRecordSize geodb `div` 4) * fromIntegral (geoDbNodeCount geodb) + 16 -- Add caching- dataAt offset = case lruget offset of- Right res -> return res- Left err -> fail err- lruget offset = unsafePerformIO $ do- cached <- LRU.lookup offset (geoLru geodb)- case cached of- Just result -> return (Right result)- Nothing -> do- let decres = decodeOrFail (BL.fromStrict $ BS.drop (offset + dataSectionStart) (geoMem geodb))- case decres of- Left (_,_,err) -> return (Left err)- Right (_,_,result) -> do- LRU.insert offset result (geoLru geodb)- return (Right result)+ dataAt offset = case decode (BS.drop (offset + dataSectionStart) (geoMem geodb)) of+ Right res -> return res+ Left err -> fail err coerceAddr | (IPv4 _) <- addr, GeoIPv4 <- geoDbAddrType geodb = return $ ipToBits addr | (IPv6 _) <- addr, GeoIPv6 <- geoDbAddrType geodb = return $ ipToBits addr
Data/GeoIP2/Fields.hs view
@@ -6,8 +6,7 @@ import Control.Applicative ((<$>)) import Control.Monad (replicateM)-import Data.Binary-import Data.Binary.Get+import Data.Serialize import Data.Bits (shift, (.&.)) import qualified Data.ByteString as BS import Data.Int@@ -16,11 +15,11 @@ import Data.ReinterpretCast (wordToDouble) import qualified Data.Text as T import Data.Text.Encoding (decodeUtf8)-import Data.Word ()+import Data.Word data GeoField = DataPointer Int64- | DataString T.Text+ | DataString !T.Text | DataDouble Double | DataInt Int64 | DataWord Word64@@ -77,10 +76,10 @@ -- | Parse number of given length parseNumber :: Num a => Int64 -> Get a parseNumber fsize = do- bytes <- getByteString (fromIntegral fsize)+ bytes <- getBytes (fromIntegral fsize) return $ BS.foldl' (\acc new -> fromIntegral new + 256 * acc) 0 bytes -instance Binary GeoField where+instance Serialize GeoField where put = undefined get = do control <- getWord8@@ -104,7 +103,7 @@ case ftype of 1 -> return $ DataPointer fsize- 2 -> DataString . decodeUtf8 <$> getByteString (fromIntegral fsize)+ 2 -> DataString . decodeUtf8 <$> getBytes (fromIntegral fsize) 3 -> DataDouble . wordToDouble <$> get 5 -> DataWord <$> parseNumber fsize 6 -> DataWord <$> parseNumber fsize@@ -119,5 +118,5 @@ 11 -> DataArray <$> replicateM (fromIntegral fsize) get 14 -> return $ DataBool (fsize == 0) _ -> do- _ <- getByteString (fromIntegral fsize)+ _ <- getBytes (fromIntegral fsize) return $ DataUnknown ftype fsize
Data/GeoIP2/SearchTree.hs view
@@ -2,11 +2,11 @@ module Data.GeoIP2.SearchTree where -import Data.Binary-import Data.Bits (shift, testBit, (.&.), (.|.))-import qualified Data.ByteString as BS+import Data.Bits (shift, testBit, (.&.), (.|.))+import qualified Data.ByteString as BS import Data.Int-import Data.IP (IP (..), fromIPv4, fromIPv6b)+import Data.IP (IP (..), fromIPv4, fromIPv6b)+import Data.Word -- | Convert byte to list of bits starting from the most significant one byteToBits :: Int -> [Bool]
README.md view
@@ -3,7 +3,7 @@ GeoIP2 is a haskell binding to the MaxMind GeoIP2 database. It parses the database according to the MaxMind DB-<a href="http://maxmind.github.io/MaxMind-DB/">specification</a>,+[specification](http://maxmind.github.io/MaxMind-DB), version 2 of the specification is supported. The free geolite2 database can be downloaded at http://dev.maxmind.com/geoip/geoip2/geolite2/.
geoip2.cabal view
@@ -1,5 +1,5 @@ name: geoip2-version: 0.1.0.3+version: 0.1.0.4 synopsis: Pure haskell interface to MaxMind GeoIP database description: GeoIP2 is a haskell binding to the MaxMind GeoIP2 database.@@ -26,11 +26,10 @@ build-depends: base >=4.7 && <4.9 , mmap , bytestring- , binary+ , cereal , text , containers , iproute(>=1.4.0) , reinterpret-cast- , lrucache default-language: Haskell2010 ghc-options: -Wall