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  }