func get(begin int64, wg *sync.WaitGroup, n *node.Node) { defer wg.Done() var res []string var err error res, err = n.Talk("/recent/"+strconv.FormatInt(begin, 10)+"-", nil) if err != nil { manager.RemoveFromAllTable(n) log.Println(err) return } err = db.DB.Update(func(tx *bolt.Tx) error { for _, line := range res { rec, errr := record.Make(line) if errr != nil { continue } appendHead(tx, rec.Head) tags := strings.Fields(strings.TrimSpace(rec.GetBodyValue("tag", ""))) if len(tags) > 0 { suggest.AddString(tx, rec.Datfile, tags) manager.AppendToTableTX(tx, rec.Datfile, n) } } return nil }) if err != nil { log.Println(err) } log.Println("added", len(res), "recent records from", n.Nodestr) }
//getWithRange gets records with range using node n and adds to cache after checking them. //if no records exist in cache, uses head //return true if gotten records>0 func getWithRange(n *node.Node, c *thread.Cache, dm *Manager) bool { got := false for { from, to := dm.Get(n) if from <= 0 { return got } var okcount int ress, err := n.Talk(fmt.Sprintf("/get/%s/%d-%d", c.Datfile, from, to), nil) if err != nil { dm.Finished(n, false) return false } err = db.DB.Update(func(tx *bolt.Tx) error { for _, res := range ress { errf := c.CheckData(tx, res, -1, "", from, to) if errf == nil { okcount++ } } return nil }) if err != nil { log.Println(err) } dm.Finished(n, true) log.Println(c.Datfile, okcount, "records were saved from", n.Nodestr) got = okcount > 0 } }
//headWithRange checks node n has records with range and adds records which should be downloaded to downloadmanager. func headWithRange(n *node.Node, c *thread.Cache, dm *Manager) bool { begin := time.Now().Unix() - cfg.GetRange if rec, err := recentlist.Newest(c.Datfile); err == nil { begin = rec.Stamp - cfg.GetRange } if cfg.GetRange == 0 || begin < 0 { begin = 0 } res, err := n.Talk(fmt.Sprintf("/head/%s/%d-", c.Datfile, begin), nil) if err != nil { return false } if len(res) == 0 { ress, errr := n.Talk(fmt.Sprintf("/have/%s", c.Datfile), nil) if errr != nil || len(ress) == 0 || ress[0] != "YES" { manager.RemoveFromTable(c.Datfile, n) } else { manager.AppendToTable(c.Datfile, n) } return false } manager.AppendToTable(c.Datfile, n) dm.Set(res, n) return true }
//GetData gets records from node n and checks its is same as stamp and id in args. //save recs if success. returns errSpam or errGet. func (r *Record) GetData(n *node.Node) error { res, err := n.Talk(fmt.Sprintf("/get/%s/%d/%s", r.Datfile, r.Stamp, r.ID), nil) if len(res) == 0 { err = errors.New("no response") } if err != nil { log.Println(err) return cfg.ErrGet } if err = r.Parse(res[0]); err != nil { return cfg.ErrGet } r.Sync() return r.CheckData(-1, -1) }
//TellUpdate makes mynode info from node or dnsname or ip addr, //and broadcast the updates of record id=id in cache c.datfile with stamp. func TellUpdate(datfile string, stamp int64, id string, n *node.Node) { const updateNodes = 10 tellstr := node.Me(true).Toxstring() if n != nil { tellstr = n.Toxstring() } msg := strings.Join([]string{"/update", datfile, strconv.FormatInt(stamp, 10), id, tellstr}, "/") ns := Get(datfile, nil) ns = ns.Extend(Get(list, nil)) ns = ns.Extend(Random(ns, updateNodes)) log.Println("telling #", len(ns)) for _, n := range ns { _, err := n.Talk(msg, nil) if err != nil { log.Println(err) } } }