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  }