github.com/vescale/zgraph@v0.0.0-20230410094002-959c02d50f95/catalog/graph.go (about) 1 // Copyright 2022 zGraph Authors. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package catalog 16 17 import ( 18 "strings" 19 "sync" 20 "sync/atomic" 21 22 "github.com/vescale/zgraph/parser/model" 23 ) 24 25 // Graph represents a runtime graph object. 26 type Graph struct { 27 // mdl preventing multiple threads change the graph metadata concurrently. 28 mdl sync.Mutex 29 30 // NOTE: DON'T CHANGE THE CONTENT OF THIS POINTER. 31 // The information object will be used by multiple package, and we need to clone a 32 // new object if we want to modify it and keep the original one immutable. 33 meta atomic.Pointer[model.GraphInfo] 34 35 labels struct { 36 sync.RWMutex 37 38 byName map[string]*Label 39 byID map[int64]*Label 40 } 41 properties struct { 42 sync.RWMutex 43 44 byName map[string]*model.PropertyInfo 45 byID map[uint16]*model.PropertyInfo 46 } 47 indexes struct { 48 sync.RWMutex 49 50 byName map[string]*Index 51 byID map[int64]*Index 52 } 53 } 54 55 // NewGraph returns a graph instance. 56 func NewGraph(meta *model.GraphInfo) *Graph { 57 g := &Graph{} 58 g.meta.Store(meta) 59 60 g.labels.byName = map[string]*Label{} 61 g.labels.byID = map[int64]*Label{} 62 for _, l := range meta.Labels { 63 label := NewLabel(l) 64 g.labels.byName[l.Name.L] = label 65 g.labels.byID[l.ID] = label 66 } 67 68 g.properties.byName = map[string]*model.PropertyInfo{} 69 g.properties.byID = map[uint16]*model.PropertyInfo{} 70 for _, p := range meta.Properties { 71 g.properties.byName[p.Name.L] = p 72 g.properties.byID[p.ID] = p 73 } 74 75 g.indexes.byName = map[string]*Index{} 76 g.indexes.byID = map[int64]*Index{} 77 for _, idx := range meta.Indexes { 78 index := NewIndex(idx) 79 g.indexes.byName[idx.Name.L] = index 80 g.indexes.byID[idx.ID] = index 81 } 82 83 return g 84 } 85 86 // Meta returns the meta information object of this graph. 87 func (g *Graph) Meta() *model.GraphInfo { 88 return g.meta.Load() 89 } 90 91 // Label returns the label of specified name. 92 func (g *Graph) Label(name string) *Label { 93 g.labels.RLock() 94 defer g.labels.RUnlock() 95 96 return g.labels.byName[strings.ToLower(name)] 97 } 98 99 // LabelByID returns the label of specified ID. 100 func (g *Graph) LabelByID(id int64) *Label { 101 g.labels.RLock() 102 defer g.labels.RUnlock() 103 104 return g.labels.byID[id] 105 } 106 107 // Property returns the property of specified name. 108 func (g *Graph) Property(name string) *model.PropertyInfo { 109 g.properties.RLock() 110 defer g.properties.RUnlock() 111 112 return g.properties.byName[strings.ToLower(name)] 113 } 114 115 // PropertyByID returns the property of specified ID. 116 func (g *Graph) PropertyByID(id uint16) *model.PropertyInfo { 117 g.properties.RLock() 118 defer g.properties.RUnlock() 119 120 return g.properties.byID[id] 121 } 122 123 // Labels returns the labels. 124 func (g *Graph) Labels() []*Label { 125 g.labels.RLock() 126 defer g.labels.RUnlock() 127 128 if len(g.labels.byID) < 1 { 129 return nil 130 } 131 labels := make([]*Label, 0, len(g.labels.byID)) 132 for _, label := range g.labels.byID { 133 labels = append(labels, label) 134 } 135 return labels 136 } 137 138 // Properties returns the Properties. 139 func (g *Graph) Properties() []*model.PropertyInfo { 140 return g.meta.Load().Properties 141 } 142 143 // CreateLabel create a new label and append to the graph labels list. 144 func (g *Graph) CreateLabel(labelInfo *model.LabelInfo) { 145 g.labels.Lock() 146 defer g.labels.Unlock() 147 148 label := NewLabel(labelInfo) 149 g.labels.byName[labelInfo.Name.L] = label 150 g.labels.byID[labelInfo.ID] = label 151 152 meta := *g.meta.Load() 153 meta.Labels = append(meta.Labels, labelInfo) 154 g.meta.Store(&meta) 155 } 156 157 // DropLabel removes specified label from graph. 158 func (g *Graph) DropLabel(labelInfo *model.LabelInfo) { 159 g.labels.Lock() 160 defer g.labels.Unlock() 161 162 delete(g.labels.byName, labelInfo.Name.L) 163 delete(g.labels.byID, labelInfo.ID) 164 165 meta := *g.meta.Load() 166 for i, l := range meta.Labels { 167 if l.ID == labelInfo.ID { 168 meta.Labels = append(meta.Labels[:i], meta.Labels[i+1:]...) 169 break 170 } 171 } 172 g.meta.Store(&meta) 173 } 174 175 // CreateProperty create a new property and append to the graph properties list. 176 func (g *Graph) CreateProperty(propertyInfo *model.PropertyInfo) { 177 g.properties.Lock() 178 defer g.properties.Unlock() 179 180 g.properties.byName[propertyInfo.Name.L] = propertyInfo 181 g.properties.byID[propertyInfo.ID] = propertyInfo 182 183 meta := *g.meta.Load() 184 meta.Properties = append(meta.Properties, propertyInfo) 185 g.meta.Store(&meta) 186 } 187 188 // DropProperty removes specified property from graph. 189 func (g *Graph) DropProperty(propertyInfo *model.PropertyInfo) { 190 g.properties.Lock() 191 defer g.properties.Unlock() 192 193 delete(g.properties.byName, propertyInfo.Name.L) 194 delete(g.properties.byID, propertyInfo.ID) 195 196 meta := *g.meta.Load() 197 for i, p := range meta.Properties { 198 if p.ID == propertyInfo.ID { 199 meta.Properties = append(meta.Properties[:i], meta.Properties[i+1:]...) 200 break 201 } 202 } 203 g.meta.Store(&meta) 204 } 205 206 // Index returns the label of specified name. 207 func (g *Graph) Index(name string) *Index { 208 g.indexes.RLock() 209 defer g.indexes.RUnlock() 210 211 return g.indexes.byName[strings.ToLower(name)] 212 } 213 214 // IndexByID returns the label of specified ID. 215 func (g *Graph) IndexByID(id int64) *Index { 216 g.indexes.RLock() 217 defer g.indexes.RUnlock() 218 219 return g.indexes.byID[id] 220 } 221 222 // Indexes returns the indexes. 223 func (g *Graph) Indexes() []*Index { 224 g.indexes.RLock() 225 defer g.indexes.RUnlock() 226 227 if len(g.indexes.byID) < 1 { 228 return nil 229 } 230 indexes := make([]*Index, 0, len(g.indexes.byID)) 231 for _, index := range g.indexes.byID { 232 indexes = append(indexes, index) 233 } 234 return indexes 235 } 236 237 // SetNextPropID sets the next property id. 238 func (g *Graph) SetNextPropID(propID uint16) { 239 meta := *g.meta.Load() 240 meta.NextPropID = propID 241 g.meta.Store(&meta) 242 } 243 244 // MDLock locks the metadata of the current graph. 245 func (g *Graph) MDLock() { 246 g.mdl.Lock() 247 } 248 249 // MDUnlock unlocks the metadata of the current graph. 250 func (g *Graph) MDUnlock() { 251 g.mdl.Unlock() 252 }