func writePagedEdges(ctx context.Context, edges <-chan *srvpb.Edge, out table.Proto, opts *Options) error { buffer := out.Buffered() log.Println("Writing EdgeSets") esb := &assemble.EdgeSetBuilder{ MaxEdgePageSize: opts.MaxPageSize, Output: func(ctx context.Context, pes *srvpb.PagedEdgeSet) error { return buffer.Put(ctx, xsrv.EdgeSetKey(pes.Source.Ticket), pes) }, OutputPage: func(ctx context.Context, ep *srvpb.EdgePage) error { return buffer.Put(ctx, xsrv.EdgePageKey(ep.PageKey), ep) }, } var grp *srvpb.EdgeGroup for e := range edges { if grp != nil && (e.Target == nil || grp.Kind != e.Kind) { if err := esb.AddGroup(ctx, grp); err != nil { for range edges { } // drain input channel return err } grp = nil } if e.Target == nil { // Head-only edge: signals a new set of edges with the same Source if err := esb.StartEdgeSet(ctx, e.Source); err != nil { return err } } else if grp == nil { grp = &srvpb.EdgeGroup{ Kind: e.Kind, Target: []*srvpb.Node{e.Target}, } } else { grp.Target = append(grp.Target, e.Target) } } if grp != nil { if err := esb.AddGroup(ctx, grp); err != nil { return err } } if err := esb.Flush(ctx); err != nil { return err } return buffer.Flush(ctx) }
func writeEdgePages(ctx context.Context, t table.Proto, edgeGroups *table.KVProto, maxEdgePageSize int) error { // TODO(schroederc): spill large PagedEdgeSets into EdgePages it, err := edgeGroups.ScanPrefix(nil, &keyvalue.Options{LargeRead: true}) if err != nil { return err } defer it.Close() log.Println("Writing EdgeSets") esb := &assemble.EdgeSetBuilder{ MaxEdgePageSize: maxEdgePageSize, Output: func(ctx context.Context, pes *srvpb.PagedEdgeSet) error { return t.Put(ctx, xrefs.EdgeSetKey(pes.EdgeSet.SourceTicket), pes) }, OutputPage: func(ctx context.Context, ep *srvpb.EdgePage) error { return t.Put(ctx, xrefs.EdgePageKey(ep.PageKey), ep) }, } for { k, v, err := it.Next() if err == io.EOF { break } else if err != nil { return fmt.Errorf("error scanning edge groups table: %v", err) } ss := strings.Split(string(k), tempTableKeySep) if len(ss) != 3 { return fmt.Errorf("invalid edge groups table key: %q", string(k)) } src := ss[0] var eg srvpb.EdgeSet_Group if err := proto.Unmarshal(v, &eg); err != nil { return fmt.Errorf("invalid edge groups table value: %v", err) } if err := esb.AddGroup(ctx, src, &eg); err != nil { return err } } return esb.Flush(ctx) }
func writeEdgePages(ctx context.Context, t table.Proto, gs graphstore.Service) error { // TODO(schroederc): spill large PagedEdgeSets into EdgePages log.Println("Writing EdgeSets") var ( lastSrc *spb.VName pes *srvpb.PagedEdgeSet grp *srvpb.EdgeSet_Group pesTotal int ) if err := gs.Scan(ctx, new(spb.ScanRequest), func(e *spb.Entry) error { if e.EdgeKind == "" { panic("non-edge entry") } if pes != nil && !compare.VNamesEqual(lastSrc, e.Source) { if grp != nil { pes.EdgeSet.Group = append(pes.EdgeSet.Group, grp) pesTotal += len(grp.TargetTicket) } pes.TotalEdges = int32(pesTotal) if err := t.Put(xsrv.EdgeSetKey(pes.EdgeSet.SourceTicket), pes); err != nil { return err } pes = nil grp = nil pesTotal = 0 } if pes == nil { pes = &srvpb.PagedEdgeSet{ EdgeSet: &srvpb.EdgeSet{ SourceTicket: kytheuri.ToString(e.Source), }, } } if grp != nil && grp.Kind != e.EdgeKind { pes.EdgeSet.Group = append(pes.EdgeSet.Group, grp) pesTotal += len(grp.TargetTicket) grp = nil } if grp == nil { grp = &srvpb.EdgeSet_Group{ Kind: e.EdgeKind, } } grp.TargetTicket = append(grp.TargetTicket, kytheuri.ToString(e.Target)) lastSrc = e.Source return nil }); err != nil { return err } if pes != nil { if grp != nil { pes.EdgeSet.Group = append(pes.EdgeSet.Group, grp) pesTotal += len(grp.TargetTicket) } pes.TotalEdges = int32(pesTotal) if err := t.Put(xsrv.EdgeSetKey(pes.EdgeSet.SourceTicket), pes); err != nil { return err } } return nil }