diff options
-rw-r--r-- | dht-client.cabal | 1 | ||||
-rw-r--r-- | examples/dhtd.hs | 28 | ||||
-rw-r--r-- | examples/testTox.hs | 11 | ||||
-rw-r--r-- | src/DebugUtil.hs | 41 |
4 files changed, 55 insertions, 26 deletions
diff --git a/dht-client.cabal b/dht-client.cabal index d6d6600e..14c691b0 100644 --- a/dht-client.cabal +++ b/dht-client.cabal | |||
@@ -146,6 +146,7 @@ library | |||
146 | ToxToXMPP | 146 | ToxToXMPP |
147 | ToxManager | 147 | ToxManager |
148 | XMPPToTox | 148 | XMPPToTox |
149 | DebugUtil | ||
149 | 150 | ||
150 | build-depends: base | 151 | build-depends: base |
151 | , containers | 152 | , containers |
diff --git a/examples/dhtd.hs b/examples/dhtd.hs index e4b10b8d..3f2a6a63 100644 --- a/examples/dhtd.hs +++ b/examples/dhtd.hs | |||
@@ -69,6 +69,7 @@ import Announcer | |||
69 | import Announcer.Tox | 69 | import Announcer.Tox |
70 | import ToxManager | 70 | import ToxManager |
71 | import Crypto.Tox -- (zeros32,SecretKey,PublicKey, generateSecretKey, toPublic, encodeSecret, decodeSecret, userKeys) | 71 | import Crypto.Tox -- (zeros32,SecretKey,PublicKey, generateSecretKey, toPublic, encodeSecret, decodeSecret, userKeys) |
72 | import DebugUtil | ||
72 | import Network.UPNP as UPNP | 73 | import Network.UPNP as UPNP |
73 | import Network.Address hiding (NodeId, NodeInfo(..)) | 74 | import Network.Address hiding (NodeId, NodeInfo(..)) |
74 | import Network.QueryResponse | 75 | import Network.QueryResponse |
@@ -124,17 +125,6 @@ import qualified Data.CyclicBuffer as CB | |||
124 | import DPut | 125 | import DPut |
125 | 126 | ||
126 | 127 | ||
127 | showReport :: [(String,String)] -> String | ||
128 | showReport kvs = showColumns $ map (\(x,y)->[x,y]) kvs | ||
129 | |||
130 | showColumns :: [[String]] -> String | ||
131 | showColumns rows = do | ||
132 | let cols = transpose rows | ||
133 | ws = map (maximum . map (succ . length)) cols | ||
134 | fs <- rows | ||
135 | _ <- take 1 fs -- Guard against empty rows so that 'last' is safe. | ||
136 | " " ++ concat (zipWith (printf "%-*s") (init ws) (init fs)) ++ last fs ++ "\n" | ||
137 | |||
138 | pshow :: Show a => a -> B.ByteString | 128 | pshow :: Show a => a -> B.ByteString |
139 | pshow = B.pack . show | 129 | pshow = B.pack . show |
140 | 130 | ||
@@ -471,19 +461,9 @@ clientSession s@Session{..} sock cnum h = do | |||
471 | >>= hPutClient h | 461 | >>= hPutClient h |
472 | #ifdef THREAD_DEBUG | 462 | #ifdef THREAD_DEBUG |
473 | ("threads", s) -> cmd0 $ do | 463 | ("threads", s) -> cmd0 $ do |
474 | threads <- threadsInformation | 464 | let want_ss = ["-v"] `isInfixOf` words s |
475 | tm <- getCurrentTime | 465 | r <- threadReport want_ss |
476 | let (ss,ts) = partition (("search" `isPrefixOf`) . lbl . snd) | 466 | hPutClient h r |
477 | threads | ||
478 | want_ss = ["-v"] `isInfixOf` words s | ||
479 | r <- forM (if want_ss then threads else ts) $ \(tid,PerThread{..}) -> do | ||
480 | stat <- threadStatus tid | ||
481 | let showStat (ThreadBlocked reason) = show reason | ||
482 | showStat stat = show stat | ||
483 | return [show lbl,show (diffUTCTime tm startTime),showStat stat] | ||
484 | hPutClient h $ unlines [ showColumns r | ||
485 | , (if want_ss then " There are " else " and ") | ||
486 | ++ show (length ss) ++ " search threads." ] | ||
487 | #endif | 467 | #endif |
488 | ("mem", s) -> cmd0 $ do | 468 | ("mem", s) -> cmd0 $ do |
489 | case s of | 469 | case s of |
diff --git a/examples/testTox.hs b/examples/testTox.hs index 45bc661e..53ed25dc 100644 --- a/examples/testTox.hs +++ b/examples/testTox.hs | |||
@@ -1,4 +1,5 @@ | |||
1 | {-# LANGUAGE NamedFieldPuns #-} | 1 | {-# LANGUAGE NamedFieldPuns #-} |
2 | import Control.Concurrent (threadDelay) | ||
2 | import Control.Concurrent.STM.TChan | 3 | import Control.Concurrent.STM.TChan |
3 | import Control.Concurrent.STM.TMChan | 4 | import Control.Concurrent.STM.TMChan |
4 | import Control.Concurrent.STM.TVar | 5 | import Control.Concurrent.STM.TVar |
@@ -6,6 +7,8 @@ import Control.Concurrent.Supply | |||
6 | import Control.Monad.STM | 7 | import Control.Monad.STM |
7 | import Crypto.Tox | 8 | import Crypto.Tox |
8 | import qualified Data.IntMap.Strict as IntMap | 9 | import qualified Data.IntMap.Strict as IntMap |
10 | import DebugUtil | ||
11 | import DPut | ||
9 | import Network.QueryResponse | 12 | import Network.QueryResponse |
10 | import Network.Socket | 13 | import Network.Socket |
11 | import Network.Tox | 14 | import Network.Tox |
@@ -14,7 +17,6 @@ import qualified Network.Tox.Crypto.Handlers as CH | |||
14 | import Network.Tox.Crypto.Transport | 17 | import Network.Tox.Crypto.Transport |
15 | import Network.Tox.DHT.Handlers as DHT | 18 | import Network.Tox.DHT.Handlers as DHT |
16 | import Network.Tox.Onion.Transport (UDPTransport) | 19 | import Network.Tox.Onion.Transport (UDPTransport) |
17 | import DPut | ||
18 | 20 | ||
19 | 21 | ||
20 | makeToxNode :: UDPTransport -> Maybe SecretKey -> IO (Tox extra) | 22 | makeToxNode :: UDPTransport -> Maybe SecretKey -> IO (Tox extra) |
@@ -71,10 +73,15 @@ main = do | |||
71 | (a_quit,_,_) <- forkTox a_Ct7g5azVcJ8KnvxzbXs9GqeqcjrP7VdZXIC'uHeTlRf False | 73 | (a_quit,_,_) <- forkTox a_Ct7g5azVcJ8KnvxzbXs9GqeqcjrP7VdZXIC'uHeTlRf False |
72 | (b_quit,_,_) <- forkTox b_OM7znaPMYkTbm'9GcZJAdnDATXmZxZ9fnaSTP3qNCZk False | 74 | (b_quit,_,_) <- forkTox b_OM7znaPMYkTbm'9GcZJAdnDATXmZxZ9fnaSTP3qNCZk False |
73 | 75 | ||
76 | threadReport False >>= putStrLn | ||
74 | 77 | ||
75 | DHT.ping (toxDHT a_Ct7g5azVcJ8KnvxzbXs9GqeqcjrP7VdZXIC'uHeTlRf) b | 78 | DHT.ping (toxDHT a_Ct7g5azVcJ8KnvxzbXs9GqeqcjrP7VdZXIC'uHeTlRf) b |
76 | 79 | ||
77 | putStrLn "Type Enter to quit..." | 80 | putStrLn "Type Enter to quit..." |
78 | getLine | 81 | getLine |
79 | 82 | ||
80 | return () | 83 | a_quit |
84 | b_quit | ||
85 | |||
86 | threadDelay 500000 | ||
87 | threadReport False >>= putStrLn | ||
diff --git a/src/DebugUtil.hs b/src/DebugUtil.hs new file mode 100644 index 00000000..e7a10397 --- /dev/null +++ b/src/DebugUtil.hs | |||
@@ -0,0 +1,41 @@ | |||
1 | {-# LANGUAGE CPP #-} | ||
2 | module DebugUtil where | ||
3 | |||
4 | import Control.Monad | ||
5 | import Data.Time.Clock | ||
6 | import Data.List | ||
7 | import Text.Printf | ||
8 | import GHC.Conc (threadStatus,ThreadStatus(..)) | ||
9 | #ifdef THREAD_DEBUG | ||
10 | import Control.Concurrent.Lifted.Instrument | ||
11 | #else | ||
12 | import Control.Concurrent.Lifted | ||
13 | import GHC.Conc (labelThread) | ||
14 | #endif | ||
15 | |||
16 | showReport :: [(String,String)] -> String | ||
17 | showReport kvs = showColumns $ map (\(x,y)->[x,y]) kvs | ||
18 | |||
19 | showColumns :: [[String]] -> String | ||
20 | showColumns rows = do | ||
21 | let cols = transpose rows | ||
22 | ws = map (maximum . map (succ . length)) cols | ||
23 | fs <- rows | ||
24 | _ <- take 1 fs -- Guard against empty rows so that 'last' is safe. | ||
25 | " " ++ concat (zipWith (printf "%-*s") (init ws) (init fs)) ++ last fs ++ "\n" | ||
26 | |||
27 | |||
28 | threadReport :: Bool -> IO String | ||
29 | threadReport want_ss = do | ||
30 | threads <- threadsInformation | ||
31 | tm <- getCurrentTime | ||
32 | let (ss,ts) = partition (("search" `isPrefixOf`) . lbl . snd) | ||
33 | threads | ||
34 | r <- forM (if want_ss then threads else ts) $ \(tid,PerThread{..}) -> do | ||
35 | stat <- threadStatus tid | ||
36 | let showStat (ThreadBlocked reason) = show reason | ||
37 | showStat stat = show stat | ||
38 | return [show lbl,show (diffUTCTime tm startTime),showStat stat] | ||
39 | return $ unlines [ showColumns r | ||
40 | , (if want_ss then " There are " else " and ") | ||
41 | ++ show (length ss) ++ " search threads." ] | ||