diff options
Diffstat (limited to 'kad/src/Network/Kademlia/Persistence.hs')
-rw-r--r-- | kad/src/Network/Kademlia/Persistence.hs | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/kad/src/Network/Kademlia/Persistence.hs b/kad/src/Network/Kademlia/Persistence.hs new file mode 100644 index 00000000..32ec169d --- /dev/null +++ b/kad/src/Network/Kademlia/Persistence.hs | |||
@@ -0,0 +1,52 @@ | |||
1 | {-# LANGUAGE NamedFieldPuns #-} | ||
2 | {-# LANGUAGE OverloadedStrings #-} | ||
3 | module Network.Kademlia.Persistence where | ||
4 | |||
5 | import Network.Kademlia.CommonAPI | ||
6 | import Network.Kademlia.Routing as R | ||
7 | |||
8 | import Control.Concurrent.STM | ||
9 | import qualified Data.Aeson as J | ||
10 | ;import Data.Aeson as J (FromJSON) | ||
11 | import qualified Data.ByteString.Lazy as L | ||
12 | import qualified Data.HashMap.Strict as HashMap | ||
13 | import Data.List | ||
14 | import qualified Data.Vector as V | ||
15 | import System.IO.Error | ||
16 | |||
17 | saveNodes :: String -> DHT -> IO () | ||
18 | saveNodes netname DHT{dhtBuckets} = do | ||
19 | bkts <- atomically $ readTVar dhtBuckets | ||
20 | let ns = map fst $ concat $ R.toList bkts | ||
21 | bs = J.encode ns | ||
22 | fname = nodesFileName netname | ||
23 | L.writeFile fname bs | ||
24 | |||
25 | loadNodes :: FromJSON ni => String -> IO [ni] | ||
26 | loadNodes netname = do | ||
27 | let fname = nodesFileName netname | ||
28 | attempt <- tryIOError $ do | ||
29 | J.decode <$> L.readFile fname | ||
30 | >>= maybe (ioError $ userError "Nothing") return | ||
31 | either (const $ fallbackLoad fname) return attempt | ||
32 | |||
33 | nodesFileName :: String -> String | ||
34 | nodesFileName netname = netname ++ "-nodes.json" | ||
35 | |||
36 | fallbackLoad :: FromJSON t => FilePath -> IO [t] | ||
37 | fallbackLoad fname = do | ||
38 | attempt <- tryIOError $ do | ||
39 | J.decode <$> L.readFile fname | ||
40 | >>= maybe (ioError $ userError "Nothing") return | ||
41 | let go r = do | ||
42 | let m = HashMap.lookup "nodes" (r :: J.Object) | ||
43 | ns0 = case m of Just (J.Array v) -> V.toList v | ||
44 | Nothing -> [] | ||
45 | ns1 = zip (map J.fromJSON ns0) ns0 | ||
46 | issuc (J.Error _,_) = False | ||
47 | issuc _ = True | ||
48 | (ss,fs) = partition issuc ns1 | ||
49 | ns = map (\(J.Success n,_) -> n) ss | ||
50 | mapM_ print (map snd fs) >> return ns | ||
51 | either (const $ return []) go attempt | ||
52 | |||