// Test full node sync. func (s *ReconSuite) TestFullSync(c *gc.C) { ptree1, cleanup, err := s.Factory() c.Assert(err, gc.IsNil) defer cleanup() ptree2, cleanup, err := s.Factory() c.Assert(err, gc.IsNil) defer cleanup() ptree1.Insert(cf.Zi(cf.P_SKS, 65537)) ptree1.Insert(cf.Zi(cf.P_SKS, 65539)) root, _ := ptree1.Root() c.Log("peer1:", recon.MustElements(root)) ptree2.Insert(cf.Zi(cf.P_SKS, 65537)) ptree2.Insert(cf.Zi(cf.P_SKS, 65541)) root, _ = ptree2.Root() c.Log("peer2:", recon.MustElements(root)) port1, port2 := portPair(c) peer1 := s.newPeer(port1, port2, recon.PeerModeGossipOnly, ptree1) peer2 := s.newPeer(port2, port1, recon.PeerModeServeOnly, ptree2) err = s.pollRootConvergence(c, peer1, peer2, ptree1, ptree2) c.Assert(err, gc.IsNil) }
func (s *PtreeSuite) TestInsertNodeSplit(c *gc.C) { root, err := s.ptree.Root() for _, sv := range root.SValues() { c.Log("SV:", sv) c.Assert(sv.Cmp(cf.Zi(cf.P_SKS, 1)), gc.Equals, 0) } // Add a bunch of nodes, enough to cause splits for i := 0; i < s.config.SplitThreshold()*4; i++ { z := cf.Zi(cf.P_SKS, i+65536) c.Log("Insert:", z) s.ptree.Insert(z) } // Remove a bunch of nodes, enough to cause joins for i := 0; i < s.config.SplitThreshold()*4; i++ { z := cf.Zi(cf.P_SKS, i+65536) c.Log("Remove:", z) s.ptree.Remove(z) } root, err = s.ptree.Root() c.Assert(err, gc.IsNil) // Insert/Remove reversible after splitting & joining? for _, sv := range root.SValues() { c.Log("SV:", sv) c.Assert(sv.Cmp(cf.Zi(cf.P_SKS, 1)), gc.Equals, 0) } c.Assert(recon.MustChildren(root), gc.HasLen, 0) c.Assert(recon.MustElements(root), gc.HasLen, 0) }
func visit(node recon.PrefixNode) { render := struct { SValues []*conflux.Zp NumElements int Key string Leaf bool Fingerprints []string Children []string }{ node.SValues(), node.Size(), node.Key().String(), node.IsLeaf(), []string{}, []string{}, } if node.IsLeaf() { for _, element := range recon.MustElements(node) { render.Fingerprints = append(render.Fingerprints, fmt.Sprintf("%x", element.Bytes())) } } for _, child := range recon.MustChildren(node) { render.Children = append(render.Children, child.Key().String()) } out, err := json.MarshalIndent(render, "", "\t") if err != nil { die(err) } os.Stdout.Write(out) os.Stdout.Write([]byte("\n")) }
func (s *PtreeSuite) TestInsertNodesNoSplit(c *gc.C) { s.ptree.Insert(cf.Zi(cf.P_SKS, 100)) s.ptree.Insert(cf.Zi(cf.P_SKS, 300)) s.ptree.Insert(cf.Zi(cf.P_SKS, 500)) root, err := s.ptree.Root() c.Assert(err, gc.IsNil) c.Assert(recon.MustElements(root), gc.HasLen, 3) c.Assert(root.IsLeaf(), gc.Equals, true) s.ptree.Remove(cf.Zi(cf.P_SKS, 100)) s.ptree.Remove(cf.Zi(cf.P_SKS, 300)) s.ptree.Remove(cf.Zi(cf.P_SKS, 500)) root, err = s.ptree.Root() c.Assert(recon.MustElements(root), gc.HasLen, 0) for _, sv := range root.SValues() { c.Assert(sv.Cmp(cf.Zi(cf.P_SKS, 1)), gc.Equals, 0) } }
// Test sync with polynomial interpolation. func (s *ReconSuite) TestPolySyncMBar(c *gc.C) { ptree1, cleanup, err := s.Factory() c.Assert(err, gc.IsNil) defer cleanup() ptree2, cleanup, err := s.Factory() c.Assert(err, gc.IsNil) defer cleanup() onlyInPeer1 := cf.NewZSet() // Load up peer 1 with items for i := 1; i < 100; i++ { ptree1.Insert(cf.Zi(cf.P_SKS, 65537*i)) } // Four extra samples for i := 1; i < 5; i++ { z := cf.Zi(cf.P_SKS, 68111*i) ptree1.Insert(z) onlyInPeer1.Add(z) } root, _ := ptree1.Root() c.Log("peer1:", recon.MustElements(root)) onlyInPeer2 := cf.NewZSet() // Load up peer 2 with items for i := 1; i < 100; i++ { ptree2.Insert(cf.Zi(cf.P_SKS, 65537*i)) } // One extra sample for i := 1; i < 2; i++ { z := cf.Zi(cf.P_SKS, 70001*i) ptree2.Insert(z) onlyInPeer2.Add(z) } root, _ = ptree2.Root() c.Log("peer2:", recon.MustElements(root)) port1, port2 := portPair(c) peer1 := s.newPeer(port1, port2, recon.PeerModeGossipOnly, ptree1) peer2 := s.newPeer(port2, port1, recon.PeerModeServeOnly, ptree2) err = s.pollConvergence(c, peer1, peer2, onlyInPeer2, onlyInPeer1, LongTimeout) c.Assert(err, gc.IsNil) }
func (s *ReconSuite) pollRootConvergence(c *gc.C, peer1, peer2 *recon.Peer, ptree1, ptree2 recon.PrefixTree) error { var t tomb.Tomb t.Go(func() error { defer peer1.Stop() defer peer2.Stop() var mu sync.Mutex var zs1 *cf.ZSet = cf.NewZSet() var zs2 *cf.ZSet = cf.NewZSet() timer := time.NewTimer(LongTimeout) peer1.SetMutatedFunc(func() { mu.Lock() root1, err := ptree1.Root() c.Assert(err, gc.IsNil) zs1 = cf.NewZSet(recon.MustElements(root1)...) mu.Unlock() }) peer2.SetMutatedFunc(func() { mu.Lock() root2, err := ptree2.Root() c.Assert(err, gc.IsNil) zs2 = cf.NewZSet(recon.MustElements(root2)...) mu.Unlock() }) POLLING: for { select { case r1, ok := <-peer1.RecoverChan: if !ok { break POLLING } c.Logf("peer1 recover: %v", r1) for _, zp := range r1.RemoteElements { c.Assert(zp, gc.NotNil) peer1.Insert(zp) } case r2, ok := <-peer2.RecoverChan: if !ok { break POLLING } c.Logf("peer2 recover: %v", r2) for _, zp := range r2.RemoteElements { c.Assert(zp, gc.NotNil) peer2.Insert(zp) } case _ = <-timer.C: return fmt.Errorf("timeout waiting for convergence") default: } var done bool mu.Lock() done = zs1.Len() > 0 && zs1.Equal(zs2) mu.Unlock() if done { c.Logf("peer1 has %q, peer2 has %q", zs1, zs2) return nil } } return fmt.Errorf("set reconciliation did not converge") }) return t.Wait() }