// 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 }