data structure for RealNode holds common config and management data

contributes to #56, #34, #2
This commit is contained in:
Trolli Schmittlauch 2020-07-07 17:34:42 +02:00
parent df7423ce2e
commit d293cc05d1
4 changed files with 55 additions and 14 deletions

View file

@ -16,10 +16,13 @@ main = do
-- ToDo: parse and pass config -- ToDo: parse and pass config
-- probably use `tomland` for that -- probably use `tomland` for that
conf <- readConfig conf <- readConfig
-- TODO: first initialise 'RealNode', then the vservers
-- ToDo: load persisted caches, bootstrapping nodes … -- ToDo: load persisted caches, bootstrapping nodes …
(serverSock, thisNode) <- fediChordInit conf (serverSock, thisNode) <- fediChordInit conf
-- currently no masking is necessary, as there is nothing to clean up -- currently no masking is necessary, as there is nothing to clean up
cacheWriterThread <- forkIO $ cacheWriter thisNode cacheWriterThread <- forkIO $ cacheWriter thisNode
thisNodeSnap <- readTVarIO thisNode
realNode <- readTVarIO $ parentRealNode thisNodeSnap
-- try joining the DHT using one of the provided bootstrapping nodes -- try joining the DHT using one of the provided bootstrapping nodes
let let
tryJoining (bn:bns) = do tryJoining (bn:bns) = do
@ -28,7 +31,7 @@ main = do
Left err -> putStrLn ("join error: " <> err) >> tryJoining bns Left err -> putStrLn ("join error: " <> err) >> tryJoining bns
Right joined -> pure $ Right joined Right joined -> pure $ Right joined
tryJoining [] = pure $ Left "Exhausted all bootstrap points for joining." tryJoining [] = pure $ Left "Exhausted all bootstrap points for joining."
joinedState <- tryJoining $ confBootstrapNodes conf joinedState <- tryJoining $ bootstrapNodes realNode
either (\err -> do either (\err -> do
-- handle unsuccessful join -- handle unsuccessful join

View file

@ -41,6 +41,7 @@ module Hash2Pub.FediChord (
, fediChordJoin , fediChordJoin
, fediChordBootstrapJoin , fediChordBootstrapJoin
, fediMainThreads , fediMainThreads
, RealNode (..)
, nodeStateInit , nodeStateInit
, mkServerSocket , mkServerSocket
, mkSendSocket , mkSendSocket
@ -90,27 +91,36 @@ import Debug.Trace (trace)
-- | initialise data structures, compute own IDs and bind to listening socket -- | initialise data structures, compute own IDs and bind to listening socket
-- ToDo: load persisted state, thus this function already operates in IO -- ToDo: load persisted state, thus this function already operates in IO
fediChordInit :: FediChordConf -> IO (Socket, LocalNodeStateSTM) fediChordInit :: FediChordConf -> IO (Socket, LocalNodeStateSTM)
fediChordInit conf = do fediChordInit initConf = do
initialState <- nodeStateInit conf let realNode = RealNode {
vservers = []
, nodeConfig = initConf
, bootstrapNodes = confBootstrapNodes initConf
}
realNodeSTM <- newTVarIO realNode
initialState <- nodeStateInit realNodeSTM
initialStateSTM <- newTVarIO initialState initialStateSTM <- newTVarIO initialState
serverSock <- mkServerSocket (getIpAddr initialState) (getDhtPort initialState) serverSock <- mkServerSocket (getIpAddr initialState) (getDhtPort initialState)
pure (serverSock, initialStateSTM) pure (serverSock, initialStateSTM)
-- | initialises the 'NodeState' for this local node. -- | initialises the 'NodeState' for this local node.
-- Separated from 'fediChordInit' to be usable in tests. -- Separated from 'fediChordInit' to be usable in tests.
nodeStateInit :: FediChordConf -> IO LocalNodeState nodeStateInit :: RealNodeSTM -> IO LocalNodeState
nodeStateInit conf = do nodeStateInit realNodeSTM = do
realNode <- readTVarIO realNodeSTM
cacheSTM <- newTVarIO initCache cacheSTM <- newTVarIO initCache
q <- atomically newTQueue q <- atomically newTQueue
let let
conf = nodeConfig realNode
vsID = 0
containedState = RemoteNodeState { containedState = RemoteNodeState {
domain = confDomain conf domain = confDomain conf
, ipAddr = confIP conf , ipAddr = confIP conf
, nid = genNodeID (confIP conf) (confDomain conf) 0 , nid = genNodeID (confIP conf) (confDomain conf) $ fromInteger vsID
, dhtPort = toEnum $ confDhtPort conf , dhtPort = toEnum $ confDhtPort conf
, servicePort = 0 , servicePort = 0
, vServerID = 0 , vServerID = vsID
} }
initialState = LocalNodeState { initialState = LocalNodeState {
nodeState = containedState nodeState = containedState
, nodeCacheSTM = cacheSTM , nodeCacheSTM = cacheSTM
@ -121,6 +131,7 @@ nodeStateInit conf = do
, lNumBestNodes = 3 , lNumBestNodes = 3
, pNumParallelQueries = 2 , pNumParallelQueries = 2
, jEntriesPerSlice = 2 , jEntriesPerSlice = 2
, parentRealNode = realNodeSTM
} }
pure initialState pure initialState

View file

@ -13,6 +13,8 @@ module Hash2Pub.FediChordTypes (
, LocalNodeState (..) , LocalNodeState (..)
, LocalNodeStateSTM , LocalNodeStateSTM
, RemoteNodeState (..) , RemoteNodeState (..)
, RealNode (..)
, RealNodeSTM
, setSuccessors , setSuccessors
, setPredecessors , setPredecessors
, NodeCache , NodeCache
@ -132,6 +134,19 @@ a `localCompare` b
wayForwards = getNodeID (b - a) wayForwards = getNodeID (b - a)
wayBackwards = getNodeID (a - b) wayBackwards = getNodeID (a - b)
-- | Data for managing the virtual server nodes of this real node.
-- Also contains shared data and config values.
-- TODO: more data structures for k-choices bookkeeping
data RealNode = RealNode
{ vservers :: [LocalNodeStateSTM]
-- ^ references to all active versers
, nodeConfig :: FediChordConf
-- ^ holds the initial configuration read at program start
, bootstrapNodes :: [(String, PortNumber)]
-- ^ nodes to be used as bootstrapping points, new ones learned during operation
}
type RealNodeSTM = TVar RealNode
-- | represents a node and all its important state -- | represents a node and all its important state
data RemoteNodeState = RemoteNodeState data RemoteNodeState = RemoteNodeState
@ -172,6 +187,8 @@ data LocalNodeState = LocalNodeState
-- ^ number of parallel sent queries -- ^ number of parallel sent queries
, jEntriesPerSlice :: Int , jEntriesPerSlice :: Int
-- ^ number of desired entries per cache slice -- ^ number of desired entries per cache slice
, parentRealNode :: RealNodeSTM
-- ^ the parent node managing this vserver instance
} }
deriving (Show, Eq) deriving (Show, Eq)

View file

@ -1,12 +1,13 @@
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedStrings #-}
module FediChordSpec where module FediChordSpec where
import Control.Concurrent.STM.TVar
import Control.Exception import Control.Exception
import Data.ASN1.Parse (runParseASN1) import Data.ASN1.Parse (runParseASN1)
import qualified Data.ByteString as BS import qualified Data.ByteString as BS
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
import Data.Maybe (fromJust, isJust) import Data.Maybe (fromJust, isJust)
import qualified Data.Set as Set import qualified Data.Set as Set
import Data.Time.Clock.POSIX import Data.Time.Clock.POSIX
import Network.Socket import Network.Socket
import Test.Hspec import Test.Hspec
@ -292,11 +293,20 @@ exampleNodeState = RemoteNodeState {
} }
exampleLocalNode :: IO LocalNodeState exampleLocalNode :: IO LocalNodeState
exampleLocalNode = nodeStateInit $ FediChordConf { exampleLocalNode = nodeStateInit =<< (newTVarIO $ RealNode {
vservers = []
, nodeConfig = exampleFediConf
, bootstrapNodes = confBootstrapNodes exampleFediConf
})
exampleFediConf :: FediChordConf
exampleFediConf = FediChordConf {
confDomain = "example.social" confDomain = "example.social"
, confIP = exampleIp , confIP = exampleIp
, confDhtPort = 2342 , confDhtPort = 2342
} }
exampleNodeDomain :: String exampleNodeDomain :: String
exampleNodeDomain = "example.social" exampleNodeDomain = "example.social"
exampleVs :: (Integral i) => i exampleVs :: (Integral i) => i