EpiChord: create a stub cache-invariant checker
rough logic is implemented, but only for successors and not predecessors. Additionally it just returns empty IO actions instead of lookup operations, until those are implemented. part of #1 Untested!
This commit is contained in:
parent
88897ea741
commit
0e33d442f9
|
@ -58,7 +58,7 @@ library
|
|||
exposed-modules: Hash2Pub.FediChord
|
||||
|
||||
-- Modules included in this library but not exported.
|
||||
-- other-modules:
|
||||
other-modules: Hash2Pub.Utils
|
||||
|
||||
-- LANGUAGE extensions used by modules in this package.
|
||||
other-extensions: GeneralizedNewtypeDeriving, DataKinds, OverloadedStrings
|
||||
|
|
|
@ -36,6 +36,8 @@ import qualified Data.ByteString.Lazy as BL
|
|||
import qualified Data.ByteString.UTF8 as BSU
|
||||
import qualified Data.ByteArray as BA
|
||||
|
||||
import Hash2Pub.Utils
|
||||
|
||||
-- define protocol constants
|
||||
-- | static definition of ID length in bits
|
||||
idBits :: Integer
|
||||
|
@ -94,7 +96,7 @@ data NodeState = NodeState {
|
|||
, apPort :: Maybe PortNumber
|
||||
-- ^ port of the ActivityPub relay and storage service
|
||||
-- might have to be queried first
|
||||
, nodeCache :: Map.Map NodeID CacheEntry
|
||||
, nodeCache :: NodeCache
|
||||
-- ^ EpiChord node cache with expiry times for nodes
|
||||
-- as the map is ordered, lookups for the closes preceding node can be done using @lookupLT@
|
||||
, successors :: [NodeID]
|
||||
|
@ -110,8 +112,13 @@ data NodeState = NodeState {
|
|||
, pNumParallelQueries :: Int
|
||||
-- ^ number of parallel sent queries
|
||||
-- needs to be parameterisable for simulation purposes
|
||||
, jEntriesPerSlice :: Int
|
||||
-- ^ number of desired entries per cache slice
|
||||
-- needs to be parameterisable for simulation purposes
|
||||
} deriving (Show)
|
||||
|
||||
type NodeCache = Map.Map NodeID CacheEntry
|
||||
|
||||
-- |an entry of the 'nodeCache'
|
||||
type CacheEntry = (
|
||||
NodeState
|
||||
|
@ -168,6 +175,44 @@ byteStringToUInteger bs = sum $ parsedBytes 0 bs
|
|||
|
||||
|
||||
|
||||
-- TODO: needs testing
|
||||
-- |checks wether the cache entries fulfill the logarithmic EpiChord invariant
|
||||
-- of having j entries per slice, and creates a list of necessary lookup actions.
|
||||
-- Should be invoked periodically.
|
||||
checkCacheSlices :: NodeState -> [IO ()]
|
||||
checkCacheSlices state =
|
||||
checkSlice jEntries (nid state) startBound lastSucc cache'
|
||||
-- TODO: do the same for predecessors
|
||||
where
|
||||
jEntries = jEntriesPerSlice state
|
||||
cache' = nodeCache state
|
||||
lastSucc = last <$> maybeEmpty (successors state)
|
||||
startBound = NodeID 2^(255::Integer) + nid state
|
||||
checkSlice :: Int -> NodeID -> NodeID -> Maybe NodeID -> NodeCache -> [IO ()]
|
||||
checkSlice _ _ _ Nothing _ = []
|
||||
checkSlice j ownID upperBound (Just lastSuccNode) cache
|
||||
| upperBound < lastSuccNode = []
|
||||
| otherwise =
|
||||
-- continuously half the DHT namespace, take the upper part as a slice,
|
||||
-- check for existing entries in that slice and create a lookup action
|
||||
-- and recursively do this on the lower half.
|
||||
-- recursion edge case: all successors/ predecessors need to be in the
|
||||
-- first slice.
|
||||
let
|
||||
diff = getNodeID $ upperBound - ownID
|
||||
lowerBound = ownID + NodeID (diff `div` 2)
|
||||
in
|
||||
-- TODO: replace empty IO actions with actual lookups
|
||||
-- TODO: validate ID before adding to cache
|
||||
case Map.lookupLT upperBound cache of
|
||||
Nothing -> return () : checkSlice j ownID lowerBound (Just lastSuccNode) cache
|
||||
Just (matchID, _) ->
|
||||
if
|
||||
matchID <= lowerBound then return () : checkSlice j ownID lowerBound (Just lastSuccNode) cache
|
||||
else
|
||||
checkSlice j ownID lowerBound (Just lastSuccNode) cache
|
||||
|
||||
|
||||
-- Todo: DHT backend can learn potential initial bootstrapping points through the instances mentioned in the received AP-relay messages
|
||||
-- needs to know its own domain anyways for ID generation
|
||||
-- persist them on disk so they can be used for all following bootstraps
|
||||
|
|
6
Hash2Pub/src/Hash2Pub/Utils.hs
Normal file
6
Hash2Pub/src/Hash2Pub/Utils.hs
Normal file
|
@ -0,0 +1,6 @@
|
|||
module Hash2Pub.Utils where
|
||||
|
||||
-- |wraps a list into a Maybe, by replacing empty lists with Nothing
|
||||
maybeEmpty :: [a] -> Maybe [a]
|
||||
maybeEmpty [] = Nothing
|
||||
maybeEmpty nonemptyList = Just nonemptyList
|
Loading…
Reference in a new issue