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