gitlab.com/SiaPrime/SiaPrime@v1.4.1/modules/gateway/persist.go (about) 1 package gateway 2 3 import ( 4 "os" 5 "path/filepath" 6 "time" 7 8 "gitlab.com/NebulousLabs/errors" 9 10 "gitlab.com/SiaPrime/SiaPrime/modules" 11 "gitlab.com/SiaPrime/SiaPrime/persist" 12 ) 13 14 const ( 15 // logFile is the name of the log file. 16 logFile = modules.GatewayDir + ".log" 17 18 // nodesFile is the name of the file that contains all seen nodes. 19 nodesFile = "nodes.json" 20 21 // persistFilename is the filename to be used when persisting gateway information to a JSON file 22 persistFilename = "gateway.json" 23 ) 24 25 // nodePersistMetadata contains the header and version strings that identify the 26 // node persist file. 27 var nodePersistMetadata = persist.Metadata{ 28 Header: "Sia Node List", 29 Version: "1.3.0", 30 } 31 32 // persistMetadata contains the header and version strings that identify the 33 // gateway persist file. 34 var persistMetadata = persist.Metadata{ 35 Header: "Gateway Persistence", 36 Version: "1.3.5", 37 } 38 39 type ( 40 // persist contains all of the persistent gateway data. 41 persistence struct { 42 RouterURL string 43 44 // rate limit settings 45 MaxDownloadSpeed int64 46 MaxUploadSpeed int64 47 48 // blacklisted IPs 49 Blacklist []string 50 } 51 ) 52 53 // nodePersistData returns the node data in the Gateway that will be saved to disk. 54 func (g *Gateway) nodePersistData() (nodes []*node) { 55 for _, node := range g.nodes { 56 nodes = append(nodes, node) 57 } 58 return 59 } 60 61 // load loads the Gateway's persistent data from disk. 62 func (g *Gateway) load() error { 63 // load nodes 64 var nodes []*node 65 var v130 bool 66 err := persist.LoadJSON(nodePersistMetadata, &nodes, filepath.Join(g.persistDir, nodesFile)) 67 if err != nil { 68 // COMPATv1.3.0 69 compatErr := g.loadv033persist() 70 if compatErr != nil { 71 return err 72 } 73 v130 = true 74 } 75 for i := range nodes { 76 g.nodes[nodes[i].NetAddress] = nodes[i] 77 } 78 79 // If we were loading a 1.3.0 gateway we are done. It doesn't have a 80 // gateway.json. 81 if v130 { 82 return nil 83 } 84 85 // load g.persist 86 err = persist.LoadJSON(persistMetadata, &g.persist, filepath.Join(g.persistDir, persistFilename)) 87 if os.IsNotExist(err) { 88 // There is no gateway.json, nothing to load. 89 return nil 90 } 91 if err != nil { 92 return errors.AddContext(err, "failed to load gateway persistence") 93 } 94 // create map from blacklist 95 for _, ip := range g.persist.Blacklist { 96 g.blacklist[ip] = struct{}{} 97 } 98 return nil 99 } 100 101 // saveSync stores the Gateway's persistent data on disk, and then syncs to 102 // disk to minimize the possibility of data loss. 103 func (g *Gateway) saveSync() error { 104 g.persist.Blacklist = make([]string, 0, len(g.blacklist)) 105 for ip := range g.blacklist { 106 g.persist.Blacklist = append(g.persist.Blacklist, ip) 107 } 108 return persist.SaveJSON(persistMetadata, g.persist, filepath.Join(g.persistDir, persistFilename)) 109 } 110 111 // saveSyncNodes stores the Gateway's persistent node data on disk, and then 112 // syncs to disk to minimize the possibility of data loss. 113 func (g *Gateway) saveSyncNodes() error { 114 return persist.SaveJSON(nodePersistMetadata, g.nodePersistData(), filepath.Join(g.persistDir, nodesFile)) 115 } 116 117 // threadedSaveLoop periodically saves the gateway nodes. 118 func (g *Gateway) threadedSaveLoop() { 119 for { 120 select { 121 case <-g.threads.StopChan(): 122 return 123 case <-time.After(saveFrequency): 124 } 125 126 func() { 127 err := g.threads.Add() 128 if err != nil { 129 return 130 } 131 defer g.threads.Done() 132 133 g.mu.Lock() 134 err = g.saveSyncNodes() 135 g.mu.Unlock() 136 if err != nil { 137 g.log.Println("ERROR: Unable to save gateway nodes:", err) 138 } 139 }() 140 } 141 } 142 143 // loadv033persist loads the v0.3.3 Gateway's persistent node data from disk. 144 func (g *Gateway) loadv033persist() error { 145 var nodes []modules.NetAddress 146 err := persist.LoadJSON(persist.Metadata{ 147 Header: "Sia Node List", 148 Version: "0.3.3", 149 }, &nodes, filepath.Join(g.persistDir, nodesFile)) 150 if err != nil { 151 return err 152 } 153 for _, addr := range nodes { 154 err := g.addNode(addr) 155 if err != nil { 156 g.log.Printf("WARN: error loading node '%v' from persist: %v", addr, err) 157 } 158 } 159 return nil 160 }