github.com/cayleygraph/cayley@v0.7.7/graph/log/graphlog.go (about)

     1  package graphlog
     2  
     3  import (
     4  	"bytes"
     5  	"sort"
     6  
     7  	"github.com/cayleygraph/cayley/graph"
     8  	"github.com/cayleygraph/quad"
     9  )
    10  
    11  type Op interface {
    12  	isOp()
    13  }
    14  
    15  var (
    16  	_ Op = NodeUpdate{}
    17  	_ Op = QuadUpdate{}
    18  )
    19  
    20  type NodeUpdate struct {
    21  	Hash   graph.ValueHash
    22  	Val    quad.Value
    23  	RefInc int
    24  }
    25  
    26  func (NodeUpdate) isOp() {}
    27  
    28  type QuadUpdate struct {
    29  	Ind  int
    30  	Quad graph.QuadHash
    31  	Del  bool
    32  }
    33  
    34  func (QuadUpdate) isOp() {}
    35  
    36  type Deltas struct {
    37  	IncNode []NodeUpdate
    38  	DecNode []NodeUpdate
    39  	QuadAdd []QuadUpdate
    40  	QuadDel []QuadUpdate
    41  }
    42  
    43  func InsertQuads(in []quad.Quad) *Deltas {
    44  	hnodes := make(map[graph.ValueHash]*NodeUpdate, len(in)*2)
    45  	quadAdd := make([]QuadUpdate, 0, len(in))
    46  	for i, qd := range in {
    47  		var q graph.QuadHash
    48  		for _, dir := range quad.Directions {
    49  			v := qd.Get(dir)
    50  			if v == nil {
    51  				continue
    52  			}
    53  			h := graph.HashOf(v)
    54  			q.Set(dir, h)
    55  			n := hnodes[h]
    56  			if n == nil {
    57  				n = &NodeUpdate{Hash: h, Val: v}
    58  				hnodes[h] = n
    59  			}
    60  			n.RefInc++
    61  		}
    62  		quadAdd = append(quadAdd, QuadUpdate{Ind: i, Quad: q})
    63  	}
    64  	incNodes := make([]NodeUpdate, 0, len(hnodes))
    65  	for _, n := range hnodes {
    66  		incNodes = append(incNodes, *n)
    67  	}
    68  	hnodes = nil
    69  	sort.Slice(incNodes, func(i, j int) bool {
    70  		return bytes.Compare(incNodes[i].Hash[:], incNodes[j].Hash[:]) < 0
    71  	})
    72  	return &Deltas{
    73  		IncNode: incNodes,
    74  		QuadAdd: quadAdd,
    75  	}
    76  }
    77  
    78  func SplitDeltas(in []graph.Delta) *Deltas {
    79  	hnodes := make(map[graph.ValueHash]*NodeUpdate, len(in)*2)
    80  	quadAdd := make([]QuadUpdate, 0, len(in))
    81  	quadDel := make([]QuadUpdate, 0, len(in)/2)
    82  	var nadd, ndel int
    83  	for i, d := range in {
    84  		dn := 0
    85  		switch d.Action {
    86  		case graph.Add:
    87  			dn = +1
    88  			nadd++
    89  		case graph.Delete:
    90  			dn = -1
    91  			ndel++
    92  		default:
    93  			panic("unknown action")
    94  		}
    95  		var q graph.QuadHash
    96  		for _, dir := range quad.Directions {
    97  			v := d.Quad.Get(dir)
    98  			if v == nil {
    99  				continue
   100  			}
   101  			h := graph.HashOf(v)
   102  			q.Set(dir, h)
   103  			n := hnodes[h]
   104  			if n == nil {
   105  				n = &NodeUpdate{Hash: h, Val: v}
   106  				hnodes[h] = n
   107  			}
   108  			n.RefInc += dn
   109  		}
   110  		u := QuadUpdate{Ind: i, Quad: q, Del: d.Action == graph.Delete}
   111  		if !u.Del {
   112  			quadAdd = append(quadAdd, u)
   113  		} else {
   114  			quadDel = append(quadDel, u)
   115  		}
   116  	}
   117  	incNodes := make([]NodeUpdate, 0, nadd)
   118  	decNodes := make([]NodeUpdate, 0, ndel)
   119  	for _, n := range hnodes {
   120  		if n.RefInc >= 0 {
   121  			incNodes = append(incNodes, *n)
   122  		} else {
   123  			decNodes = append(decNodes, *n)
   124  		}
   125  	}
   126  	sort.Slice(incNodes, func(i, j int) bool {
   127  		return bytes.Compare(incNodes[i].Hash[:], incNodes[j].Hash[:]) < 0
   128  	})
   129  	sort.Slice(decNodes, func(i, j int) bool {
   130  		return bytes.Compare(decNodes[i].Hash[:], decNodes[j].Hash[:]) < 0
   131  	})
   132  	hnodes = nil
   133  	return &Deltas{
   134  		IncNode: incNodes, DecNode: decNodes,
   135  		QuadAdd: quadAdd, QuadDel: quadDel,
   136  	}
   137  }