-- This Source Code Form is subject to the terms of the Mozilla Public -- License, v. 2.0. If a copy of the MPL was not distributed with this -- file, You can obtain one at http://mozilla.org/MPL/2.0/. {-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-} module Database.CQL.IO.Cluster.Host where import Control.Lens (Lens') import Database.CQL.Protocol (Response (..)) import Database.CQL.IO.Cluster.Discovery import Data.IP import Data.Text (Text, unpack) import Network.Socket (SockAddr (..), PortNumber) -- | A Cassandra host known to the client. data Host = Host { _hostAddr :: !InetAddr , _dataCentre :: !Text , _rack :: !Text } instance Eq Host where a == b = _hostAddr a == _hostAddr b instance Ord Host where compare a b = compare (_hostAddr a) (_hostAddr b) peer2Host :: PortNumber -> Peer -> Host peer2Host i p = Host (ip2inet i (peerRPC p)) (peerDC p) (peerRack p) updateHost :: Host -> Maybe (Text, Text) -> Host updateHost h (Just (dc, rk)) = h { _dataCentre = dc, _rack = rk } updateHost h Nothing = h -- | A response that is known to originate from a specific 'Host'. data HostResponse k a b = HostResponse { hrHost :: !Host , hrResponse :: !(Response k a b) } deriving (Show) -- | This event will be passed to a 'Policy' to inform it about -- cluster changes. data HostEvent = HostNew !Host -- ^ a new host has been added to the cluster | HostGone !InetAddr -- ^ a host has been removed from the cluster | HostUp !InetAddr -- ^ a host has been started | HostDown !InetAddr -- ^ a host has been stopped -- | The IP address and port number of a host. hostAddr :: Lens' Host InetAddr hostAddr f ~(Host a c r) = fmap (\x -> Host x c r) (f a) {-# INLINE hostAddr #-} -- | The data centre name (may be an empty string). dataCentre :: Lens' Host Text dataCentre f ~(Host a c r) = fmap (\x -> Host a x r) (f c) {-# INLINE dataCentre #-} -- | The rack name (may be an empty string). rack :: Lens' Host Text rack f ~(Host a c r) = fmap (\x -> Host a c x) (f r) {-# INLINE rack #-} instance Show Host where show h = showString (unpack (_dataCentre h)) . showString ":" . showString (unpack (_rack h)) . showString ":" . shows (_hostAddr h) $ "" ----------------------------------------------------------------------------- -- InetAddr newtype InetAddr = InetAddr { sockAddr :: SockAddr } deriving (Eq, Ord) instance Show InetAddr where show (InetAddr (SockAddrInet p a)) = let i = fromIntegral p :: Int in shows (fromHostAddress a) . showString ":" . shows i $ "" show (InetAddr (SockAddrInet6 p _ a _)) = let i = fromIntegral p :: Int in shows (fromHostAddress6 a) . showString ":" . shows i $ "" show (InetAddr (SockAddrUnix unix)) = unix #if MIN_VERSION_network(2,6,1) && !MIN_VERSION_network(3,0,0) show (InetAddr (SockAddrCan int32)) = show int32 #endif -- | Map a 'SockAddr' into an 'InetAddr', using the given port number. sock2inet :: PortNumber -> SockAddr -> InetAddr sock2inet i (SockAddrInet _ a) = InetAddr (SockAddrInet i a) sock2inet i (SockAddrInet6 _ f a b) = InetAddr (SockAddrInet6 i f a b) sock2inet _ unix = InetAddr unix -- | Map an 'IP' into an 'InetAddr', using the given port number. ip2inet :: PortNumber -> IP -> InetAddr ip2inet p (IPv4 a) = InetAddr $ SockAddrInet p (toHostAddress a) ip2inet p (IPv6 a) = InetAddr $ SockAddrInet6 p 0 (toHostAddress6 a) 0