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

View file

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

View file

@ -13,6 +13,8 @@ module Hash2Pub.FediChordTypes (
, LocalNodeState (..)
, LocalNodeStateSTM
, RemoteNodeState (..)
, RealNode (..)
, RealNodeSTM
, setSuccessors
, setPredecessors
, NodeCache
@ -132,6 +134,19 @@ a `localCompare` b
wayForwards = getNodeID (b - a)
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
data RemoteNodeState = RemoteNodeState
@ -172,6 +187,8 @@ data LocalNodeState = LocalNodeState
-- ^ number of parallel sent queries
, jEntriesPerSlice :: Int
-- ^ number of desired entries per cache slice
, parentRealNode :: RealNodeSTM
-- ^ the parent node managing this vserver instance
}
deriving (Show, Eq)

View file

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