diff --git a/lib/main.go b/lib/main.go index 3aab9391..c16cf581 100644 --- a/lib/main.go +++ b/lib/main.go @@ -731,6 +731,76 @@ func (obj *Main) Run() error { continue } + // XXX: Should this run earlier or later than here? + // run Send/Recv on the new graph with data from the old + // graph, so that we won't need to unnecessarily re-make + // a resource that had previously received some data and + // is now different than the equivalent resource in this + // new incoming graph! + if err := obj.ge.Apply(func(g *pgraph.Graph) error { // apply runs on nextGraph (new) + old := obj.ge.Graph() + if old.NumVertices() == 0 { // skip initial empty graph + return nil + } + mapped, err := engine.ResGraphMapper(old, g) // (map[engine.RecvableRes]engine.RecvableRes, error) + if err != nil { + return err + } + + for _, v := range g.Vertices() { + res, ok := v.(engine.RecvableRes) + if !ok { + continue // we'll catch the error later! + } + + if obj.Flags.Debug { + Logf("SendRecv: %s", res) // receiving here + } + + // This mapping function is used to + // replace the Recv() function that is + // called in Send/Recv so that our new + // resources in the graph we're about to + // graphsync on can use the Recv() func + // from the current (possibly stale) + // resources so that they have the + // current values they've already + // received. This is needed so that the + // compare doesn't fail unnecessarily if + // the new resource doesn't happen to + // have the field value as whatever the + // older one previously received. It is + // important to not remake resources + // unnecessarily because doing so resets + // any important private struct fields + // that they might have. + fn := func(r engine.RecvableRes) (map[string]*engine.Send, error) { + old, exists := mapped[r] // r is new + if !exists { // initial graph could be empty + // possible programming error? + //return nil, fmt.Errorf("could not find a match for %p %s", r, r) + //return r.Recv(), nil // NO! + return map[string]*engine.Send{}, nil + } + return old.Recv(), nil // swap + } + if updated, err := graph.SendRecv(res, fn); err != nil { + return errwrap.Wrapf(err, "could not SendRecv") + } else if as := graph.UpdatedStrings(updated); len(as) > 0 { + for _, s := range as { + Logf("SendRecv: %s", s) + } + } + } + + return nil + + }); err != nil { // apply an operation to the new graph + obj.ge.Abort() // delete graph + Logf("error applying operation to the new graph: %+v", err) + continue + } + // Double check before we commit. if err := obj.ge.Apply(func(graph *pgraph.Graph) error { _, e := graph.TopologicalSort() // am i a dag or not?