summaryrefslogtreecommitdiff
path: root/kad/src/Network/Kademlia/Persistence.hs
diff options
context:
space:
mode:
Diffstat (limited to 'kad/src/Network/Kademlia/Persistence.hs')
-rw-r--r--kad/src/Network/Kademlia/Persistence.hs52
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 #-}
3module Network.Kademlia.Persistence where
4
5import Network.Kademlia.CommonAPI
6import Network.Kademlia.Routing as R
7
8import Control.Concurrent.STM
9import qualified Data.Aeson as J
10 ;import Data.Aeson as J (FromJSON)
11import qualified Data.ByteString.Lazy as L
12import qualified Data.HashMap.Strict as HashMap
13import Data.List
14import qualified Data.Vector as V
15import System.IO.Error
16
17saveNodes :: String -> DHT -> IO ()
18saveNodes 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
25loadNodes :: FromJSON ni => String -> IO [ni]
26loadNodes 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
33nodesFileName :: String -> String
34nodesFileName netname = netname ++ "-nodes.json"
35
36fallbackLoad :: FromJSON t => FilePath -> IO [t]
37fallbackLoad 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