graphmanager.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /*
  2. * EliasDB
  3. *
  4. * Copyright 2016 Matthias Ladkau. All rights reserved.
  5. *
  6. * This Source Code Form is subject to the terms of the Mozilla Public
  7. * License, v. 2.0. If a copy of the MPL was not distributed with this
  8. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  9. */
  10. package graph
  11. import (
  12. "fmt"
  13. "sort"
  14. "strconv"
  15. "sync"
  16. "devt.de/krotik/eliasdb/graph/data"
  17. "devt.de/krotik/eliasdb/graph/graphstorage"
  18. "devt.de/krotik/eliasdb/graph/util"
  19. )
  20. /*
  21. Manager data structure
  22. */
  23. type Manager struct {
  24. gs graphstorage.Storage // Graph storage of this graph manager
  25. gr *graphRulesManager // Manager for graph rules
  26. nm *util.NamesManager // Manager object which manages name encodings
  27. mapCache map[string]map[string]string // Cache which caches maps stored in the main database
  28. mutex *sync.RWMutex // Mutex to protect atomic graph operations
  29. storageMutex *sync.Mutex // Special mutex for storage object access
  30. }
  31. /*
  32. NewGraphManager returns a new GraphManager instance.
  33. */
  34. func NewGraphManager(gs graphstorage.Storage) *Manager {
  35. gm := createGraphManager(gs)
  36. gm.SetGraphRule(&SystemRuleDeleteNodeEdges{})
  37. gm.SetGraphRule(&SystemRuleUpdateNodeStats{})
  38. return gm
  39. }
  40. /*
  41. createGraphManager creates a new GraphManager instance.
  42. */
  43. func createGraphManager(gs graphstorage.Storage) *Manager {
  44. mdb := gs.MainDB()
  45. // Check version
  46. if version, ok := mdb[MainDBVersion]; !ok {
  47. mdb[MainDBVersion] = strconv.Itoa(VERSION)
  48. gs.FlushMain()
  49. } else {
  50. if v, _ := strconv.Atoi(version); v > VERSION {
  51. panic(fmt.Sprintf("Cannot open graph storage of version: %v - "+
  52. "max supported version: %v", version, VERSION))
  53. } else if v < VERSION {
  54. // Update the version if it is older
  55. mdb[MainDBVersion] = strconv.Itoa(VERSION)
  56. gs.FlushMain()
  57. }
  58. }
  59. gm := &Manager{gs, &graphRulesManager{nil, make(map[string]Rule),
  60. make(map[int]map[string]Rule)}, util.NewNamesManager(mdb),
  61. make(map[string]map[string]string), &sync.RWMutex{}, &sync.Mutex{}}
  62. gm.gr.gm = gm
  63. return gm
  64. }
  65. /*
  66. Name returns the name of this graph manager.
  67. */
  68. func (gm *Manager) Name() string {
  69. return fmt.Sprint("Graph ", gm.gs.Name())
  70. }
  71. /*
  72. SetGraphRule sets a GraphRule.
  73. */
  74. func (gm *Manager) SetGraphRule(rule Rule) {
  75. gm.gr.SetGraphRule(rule)
  76. }
  77. /*
  78. GraphRules returns a list of all available graph rules.
  79. */
  80. func (gm *Manager) GraphRules() []string {
  81. return gm.gr.GraphRules()
  82. }
  83. /*
  84. NodeIndexQuery returns an object to query the full text search index for nodes.
  85. */
  86. func (gm *Manager) NodeIndexQuery(part string, kind string) (IndexQuery, error) {
  87. iht, err := gm.getNodeIndexHTree(part, kind, false)
  88. if err != nil || iht == nil {
  89. return nil, err
  90. }
  91. return util.NewIndexManager(iht), nil
  92. }
  93. /*
  94. EdgeIndexQuery returns an object to query the full text search index for edges.
  95. */
  96. func (gm *Manager) EdgeIndexQuery(part string, kind string) (IndexQuery, error) {
  97. iht, err := gm.getEdgeIndexHTree(part, kind, false)
  98. if err != nil || iht == nil {
  99. return nil, err
  100. }
  101. return util.NewIndexManager(iht), nil
  102. }
  103. /*
  104. Partitions returns all existing partitions.
  105. */
  106. func (gm *Manager) Partitions() []string {
  107. return gm.mainStringList(MainDBParts)
  108. }
  109. /*
  110. NodeKinds returns all possible node kinds.
  111. */
  112. func (gm *Manager) NodeKinds() []string {
  113. return gm.mainStringList(MainDBNodeKinds)
  114. }
  115. /*
  116. EdgeKinds returns all possible node kinds.
  117. */
  118. func (gm *Manager) EdgeKinds() []string {
  119. return gm.mainStringList(MainDBEdgeKinds)
  120. }
  121. /*
  122. NodeAttrs returns all possible node attributes for a given node kind.
  123. */
  124. func (gm *Manager) NodeAttrs(kind string) []string {
  125. return gm.mainStringList(MainDBNodeAttrs + kind)
  126. }
  127. /*
  128. NodeEdges returns all possible node edge specs for a given node kind.
  129. */
  130. func (gm *Manager) NodeEdges(kind string) []string {
  131. return gm.mainStringList(MainDBNodeEdges + kind)
  132. }
  133. /*
  134. EdgeAttrs returns all possible edge attributes for a given edge kind.
  135. */
  136. func (gm *Manager) EdgeAttrs(kind string) []string {
  137. return gm.mainStringList(MainDBEdgeAttrs + kind)
  138. }
  139. /*
  140. mainStringList return a list in the MainDB.
  141. */
  142. func (gm *Manager) mainStringList(name string) []string {
  143. items := gm.getMainDBMap(name)
  144. var ret []string
  145. if items != nil {
  146. for item := range items {
  147. ret = append(ret, item)
  148. }
  149. }
  150. sort.StringSlice(ret).Sort()
  151. return ret
  152. }
  153. /*
  154. IsValidAttr checks if a given string can be a valid node attribute.
  155. */
  156. func (gm *Manager) IsValidAttr(attr string) bool {
  157. return gm.nm.Encode32(attr, false) != "" ||
  158. attr == data.NodeKey || attr == data.NodeKind ||
  159. attr == data.EdgeEnd1Key || attr == data.EdgeEnd1Kind ||
  160. attr == data.EdgeEnd1Role || attr == data.EdgeEnd1Cascading ||
  161. attr == data.EdgeEnd2Key || attr == data.EdgeEnd2Kind ||
  162. attr == data.EdgeEnd2Role || attr == data.EdgeEnd2Cascading
  163. }