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 }