summaryrefslogtreecommitdiff
path: root/kad/tests/searchCancel.hs
blob: 859866741c8438f601dddbe043b94736774c027a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import Control.Concurrent
import Control.Concurrent.STM
import Control.Monad
import Data.Bits

import Network.Kademlia
import Network.Kademlia.Bootstrap
import Network.Kademlia.CommonAPI
import Network.Kademlia.Persistence
import Network.Kademlia.Routing
import Network.Kademlia.Search

import qualified Data.MinMaxPSQ as MM
import qualified Data.Set as Set

makeSchResults :: TVar (Maybe (SearchState Int Int () Int Int)) -> TVar Int -> IO (Maybe ([Int],[Int],Maybe ()))
makeSchResults mbv var = do
    threadDelay 200000
    (r,io) <- atomically $ do
        n <- readTVar var
        let ns = take 4 [n .. ]
        writeTVar var $! n + 4
        let r = Just (ns, ns, Just ()) -- Maybe ([ni], [r], Maybe tok)
            stmio = if n > 490
                        then do
                            ms <- readTVar mbv
                            case ms of
                                Just s -> do report <- showSearchState s
                                             return $ putStrLn $ "cnt=" ++ show n ++ " " ++ report
                                _ -> return $ return ()
                        else return $ return ()
        io <- stmio
        return (r,io)
    io
    return r

kad :: KademliaSpace Int Int
kad = KademliaSpace
    { kademliaLocation = id
    , kademliaTestBit  = \x i -> testBit i x
    , kademliaXor      = \x y -> abs (x - y)
    , kademliaSample   = \_ x _ -> pure x
    }

sch :: TVar (Maybe (SearchState Int Int () Int Int)) -> TVar Int -> Search Int Int () Int Int
sch mbv var = Search
    { searchSpace       = kad
    , searchNodeAddress = id
    , searchQuery       = \_ _ -> makeSchResults mbv var
    , searchAlpha       = 4
    , searchK           = 8
    }

onResult :: Int -> STM Bool
onResult k = return (k < 50000)

showSearchState st = do
    pc <- readTVar (searchPendingCount st)
    q <- readTVar (searchQueued st)
    inf <- readTVar (searchInformant st)
    vset <- readTVar (searchVisited st)
    return $ unwords
        [ "pending=" ++ show pc
        , "|q|=" ++ show (maybe 0 MM.size q)
        , "|inf|=" ++ show (MM.size inf)
        , "|visited|=" ++ show (Set.size vset)
        ]

main = do
    var <- newTVarIO 5
    fin <- newTVarIO False
    mbstvar <- newTVarIO Nothing
    s <- atomically $ newSearch (sch mbstvar var) maxBound [1..4]
    atomically $ writeTVar mbstvar (Just s)
    t <- forkIO $ do searchLoop (sch mbstvar var) maxBound onResult s
                     atomically $ writeTVar fin True

    putStrLn "Waiting on counter."
    (done,n) <- atomically $ do
        done <- readTVar fin
        n <- readTVar var
        if (not done && n < 500)
            then retry
            else return (done,n)
    putStrLn $ "(done,n) = " ++ show (done,n)
    report <- atomically $ do
        report <- showSearchState s
        searchCancel s
        return report
    putStrLn report
    putStrLn "Canceled.  Awaiting fin.  The program should quit shortly without much output after this."

    forkIO $
        let loop = do
                (x,report) <- atomically $ (,) <$> readTVar var <*> showSearchState s
                putStrLn $ "query after cancel! " ++ show x ++ " " ++ report
                atomically $ readTVar var >>= \y -> if x == y then retry else return ()
                loop
        in loop
    atomically $ check =<< readTVar fin