// Save the current set of reachable DHT nodes to disk. func Save(filename string, dht *dht.DHT) error { d := doc{ NodeID: dht.NodeID(), } nodes := dht.ListReachableNodes() for i := range nodes { d.Nodes = append(d.Nodes, node{ NodeID: nodes[i].NodeID.String(), Addr: nodes[i].Addr.String(), }) } b, err := json.Marshal(&d) if err != nil { return err } tfilename := filename + ".tmp" defer os.Remove(tfilename) err = ioutil.WriteFile(tfilename, b, 0644) if err != nil { return err } return os.Rename(tfilename, filename) }
// Loads the node database into the running DHT. Call this just after running the DHT. func (ds *DHTStorage) LoadDHT(d *dht.DHT) error { db, err := ds.getDB() if err != nil { return err } defer db.Close() err = ds.createTablesWith(db) if err != nil { return err } r, err := db.Query(`SELECT hostname,node_id FROM dht_routers`) if err != nil { return err } defer r.Close() for r.Next() { var hostname string var node_id interface{} err = r.Scan(&hostname, &node_id) if err != nil { return err } node_id_s, ok := node_id.([]byte) if !ok { node_id_s = []byte{} } node_id_bin, err := hex.DecodeString(string(node_id_s)) if err != nil { node_id_bin = []byte{} } unused(node_id) d.AddNode(hostname, string(node_id_bin)) } return nil }
// Saves the node database into the DHT. Call this periodically or just before stopping the DHT. // The current Node ID and port number are also saved. func (ds *DHTStorage) SaveDHT(d *dht.DHT) error { db, err := ds.getDB() if err != nil { return err } defer db.Close() now := time.Now() err = ds.createTablesWith(db) if err != nil { return err } tx, err := db.Begin() if err != nil { return err } _, err = tx.Exec(`UPDATE dht_routers SET old=1;`) if err != nil { return err } err = d.VisitNodes(func(addr string, nodeID []byte) error { _, err := tx.Exec(`INSERT OR IGNORE INTO dht_routers (hostname,first_seen,old) VALUES (?,?,0);`, addr, now) if err != nil { return err } _, err = tx.Exec(`UPDATE dht_routers SET node_id=?, last_seen=?, old=0 WHERE hostname=?;`, hex.EncodeToString(nodeID), now, addr) if err != nil { return err } return nil }) if err != nil { return err } _, err = tx.Exec(`DELETE FROM dht_routers WHERE old=1 AND last_seen < date('now','-2 hours');`) if err != nil { return err } _, err = tx.Exec(`UPDATE dht_routers SET first_seen=? WHERE first_seen IS NULL`, time.Now()) if err != nil { return err } _, err = tx.Exec(`INSERT OR REPLACE INTO dht_settings (key,value) VALUES ('port',?)`, d.Port()) if err != nil { return err } tx.Commit() return nil }