graphmanager_edges.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816
  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. "encoding/binary"
  13. "encoding/gob"
  14. "fmt"
  15. "sort"
  16. "strings"
  17. "devt.de/krotik/eliasdb/graph/data"
  18. "devt.de/krotik/eliasdb/graph/util"
  19. "devt.de/krotik/eliasdb/hash"
  20. )
  21. /*
  22. edgeTargetInfo is an internal structure which stores edge information
  23. */
  24. type edgeTargetInfo struct {
  25. CascadeToTarget bool // Flag if delete operations should be cascaded to the target
  26. CascadeLastToTarget bool // Flag if delete operations should be cascaded to the target after the last edge was deleted
  27. CascadeFromTarget bool // Flag if delete operations should be cascaded from the target after the last edge was deleted
  28. CascadeLastFromTarget bool // Flag if delete operations should be cascaded from the target
  29. TargetNodeKey string // Key of the target node
  30. TargetNodeKind string // Kind of the target ndoe
  31. }
  32. func init() {
  33. // Make sure we can use the relevant types in a gob operation
  34. gob.Register(make(map[string]string))
  35. gob.Register(make(map[string]*edgeTargetInfo))
  36. gob.Register(&edgeTargetInfo{})
  37. }
  38. /*
  39. EdgeCount returns the edge count for a given edge kind.
  40. */
  41. func (gm *Manager) EdgeCount(kind string) uint64 {
  42. if val, ok := gm.gs.MainDB()[MainDBEdgeCount+kind]; ok {
  43. return binary.LittleEndian.Uint64([]byte(val))
  44. }
  45. return 0
  46. }
  47. /*
  48. FetchNodeEdgeSpecs returns all possible edge specs for a certain node.
  49. */
  50. func (gm *Manager) FetchNodeEdgeSpecs(part string, key string, kind string) ([]string, error) {
  51. _, tree, err := gm.getNodeStorageHTree(part, kind, false)
  52. if err != nil || tree == nil {
  53. return nil, err
  54. }
  55. // Take reader lock
  56. gm.mutex.RLock()
  57. defer gm.mutex.RUnlock()
  58. specsNodeKey := PrefixNSSpecs + key
  59. obj, err := tree.Get([]byte(specsNodeKey))
  60. if err != nil {
  61. return nil, &util.GraphError{Type: util.ErrReading, Detail: err.Error()}
  62. } else if obj == nil {
  63. return nil, nil
  64. }
  65. specsNodeMap := obj.(map[string]string)
  66. specsNode := make([]string, 0, len(specsNodeMap))
  67. for spec := range specsNodeMap {
  68. role1 := gm.nm.Decode16(spec[:2])
  69. relKind := gm.nm.Decode16(spec[2:4])
  70. role2 := gm.nm.Decode16(spec[4:6])
  71. end2Kind := gm.nm.Decode16(spec[6:])
  72. specsNode = append(specsNode,
  73. role1+":"+relKind+":"+role2+":"+end2Kind)
  74. }
  75. // Ensure the output is deterministic
  76. sort.StringSlice(specsNode).Sort()
  77. return specsNode, nil
  78. }
  79. /*
  80. TraverseMulti traverses from a given node to other nodes following a given
  81. partial edge spec. Since the edge spec can be partial it is possible to
  82. traverse multiple edge kinds. A spec with the value ":::" would follow
  83. all relationships. The last parameter allData specifies if all data
  84. should be retrieved for the connected nodes and edges. If set to false only
  85. the minimal set of attributes will be populated.
  86. */
  87. func (gm *Manager) TraverseMulti(part string, key string, kind string,
  88. spec string, allData bool) ([]data.Node, []data.Edge, error) {
  89. sspec := strings.Split(spec, ":")
  90. if len(sspec) != 4 {
  91. return nil, nil, &util.GraphError{Type: util.ErrInvalidData, Detail: "Invalid spec: " + spec}
  92. } else if IsFullSpec(spec) {
  93. return gm.Traverse(part, key, kind, spec, allData)
  94. }
  95. // Get all specs for the given node
  96. specs, err := gm.FetchNodeEdgeSpecs(part, key, kind)
  97. if err != nil || specs == nil {
  98. return nil, nil, err
  99. }
  100. matchSpec := func(spec string) bool {
  101. mspec := strings.Split(spec, ":")
  102. // Check spec components
  103. if (sspec[0] != "" && mspec[0] != sspec[0]) ||
  104. (sspec[1] != "" && mspec[1] != sspec[1]) ||
  105. (sspec[2] != "" && mspec[2] != sspec[2]) ||
  106. (sspec[3] != "" && mspec[3] != sspec[3]) {
  107. return false
  108. }
  109. return true
  110. }
  111. // Match specs and collect the results
  112. var nodes []data.Node
  113. var edges []data.Edge
  114. for _, rspec := range specs {
  115. if spec == ":::" || matchSpec(rspec) {
  116. sn, se, err := gm.Traverse(part, key, kind, rspec, allData)
  117. if err != nil {
  118. return nil, nil, err
  119. }
  120. nodes = append(nodes, sn...)
  121. edges = append(edges, se...)
  122. }
  123. }
  124. return nodes, edges, nil
  125. }
  126. /*
  127. Traverse traverses from a given node to other nodes following a given edge spec.
  128. The last parameter allData specifies if all data should be retrieved for
  129. the connected nodes and edges. If set to false only the minimal set of
  130. attributes will be populated.
  131. */
  132. func (gm *Manager) Traverse(part string, key string, kind string,
  133. spec string, allData bool) ([]data.Node, []data.Edge, error) {
  134. _, tree, err := gm.getNodeStorageHTree(part, kind, false)
  135. if err != nil || tree == nil {
  136. return nil, nil, err
  137. }
  138. // Take reader lock
  139. gm.mutex.RLock()
  140. defer gm.mutex.RUnlock()
  141. sspec := strings.Split(spec, ":")
  142. if len(sspec) != 4 {
  143. return nil, nil, &util.GraphError{Type: util.ErrInvalidData, Detail: "Invalid spec: " + spec}
  144. } else if !IsFullSpec(spec) {
  145. return nil, nil, &util.GraphError{Type: util.ErrInvalidData, Detail: "Invalid spec: " + spec +
  146. " - spec needs to be fully specified for direct traversal"}
  147. }
  148. encspec := gm.nm.Encode16(sspec[0], false) + gm.nm.Encode16(sspec[1], false) +
  149. gm.nm.Encode16(sspec[2], false) + gm.nm.Encode16(sspec[3], false)
  150. edgeInfoKey := PrefixNSEdge + key + encspec
  151. // Lookup the target map containing edgeTargetInfo objects
  152. obj, err := tree.Get([]byte(edgeInfoKey))
  153. if err != nil || obj == nil {
  154. return nil, nil, err
  155. }
  156. targetMap := obj.(map[string]*edgeTargetInfo)
  157. nodes := make([]data.Node, 0, len(targetMap))
  158. edges := make([]data.Edge, 0, len(targetMap))
  159. if !allData {
  160. // Populate nodes and edges with the minimal set of attributes
  161. // no further lookups required
  162. for k, v := range targetMap {
  163. edge := data.NewGraphEdge()
  164. edge.SetAttr(data.NodeKey, k)
  165. edge.SetAttr(data.NodeKind, sspec[1])
  166. edge.SetAttr(data.EdgeEnd1Key, key)
  167. edge.SetAttr(data.EdgeEnd1Kind, kind)
  168. edge.SetAttr(data.EdgeEnd1Role, sspec[0])
  169. edge.SetAttr(data.EdgeEnd1Cascading, v.CascadeToTarget)
  170. edge.SetAttr(data.EdgeEnd1CascadingLast, v.CascadeLastToTarget)
  171. edge.SetAttr(data.EdgeEnd2Key, v.TargetNodeKey)
  172. edge.SetAttr(data.EdgeEnd2Kind, v.TargetNodeKind)
  173. edge.SetAttr(data.EdgeEnd2Role, sspec[2])
  174. edge.SetAttr(data.EdgeEnd2Cascading, v.CascadeFromTarget)
  175. edge.SetAttr(data.EdgeEnd2CascadingLast, v.CascadeLastFromTarget)
  176. edges = append(edges, edge)
  177. node := data.NewGraphNode()
  178. node.SetAttr(data.NodeKey, v.TargetNodeKey)
  179. node.SetAttr(data.NodeKind, v.TargetNodeKind)
  180. nodes = append(nodes, node)
  181. }
  182. } else {
  183. // Get the HTrees which stores the edges
  184. edgeht, err := gm.getEdgeStorageHTree(part, sspec[1], false)
  185. if err != nil || edgeht == nil {
  186. return nil, nil, err
  187. }
  188. for k, v := range targetMap {
  189. // Read the edge from the datastore
  190. edgenode, err := gm.readNode(k, sspec[1], nil, edgeht, edgeht)
  191. if err != nil || edgenode == nil {
  192. return nil, nil, err
  193. }
  194. edge := data.NewGraphEdgeFromNode(edgenode)
  195. // Exchange ends if necessary
  196. if edge.End2Key() == key && edge.End2Kind() == kind {
  197. swap := func(attr1 string, attr2 string) {
  198. tmp := edge.Attr(attr1)
  199. edge.SetAttr(attr1, edge.Attr(attr2))
  200. edge.SetAttr(attr2, tmp)
  201. }
  202. swap(data.EdgeEnd1Key, data.EdgeEnd2Key)
  203. swap(data.EdgeEnd1Kind, data.EdgeEnd2Kind)
  204. swap(data.EdgeEnd1Role, data.EdgeEnd2Role)
  205. swap(data.EdgeEnd1Cascading, data.EdgeEnd2Cascading)
  206. }
  207. edges = append(edges, edge)
  208. // Get the HTrees which stores the node
  209. attht, valht, err := gm.getNodeStorageHTree(part, v.TargetNodeKind, false)
  210. if err != nil || attht == nil || valht == nil {
  211. return nil, nil, err
  212. }
  213. node, err := gm.readNode(v.TargetNodeKey, v.TargetNodeKind, nil, attht, valht)
  214. if err != nil {
  215. return nil, nil, err
  216. }
  217. nodes = append(nodes, node)
  218. }
  219. }
  220. return nodes, edges, nil
  221. }
  222. /*
  223. FetchEdge fetches a single edge from a partition of the graph.
  224. */
  225. func (gm *Manager) FetchEdge(part string, key string, kind string) (data.Edge, error) {
  226. return gm.FetchEdgePart(part, key, kind, nil)
  227. }
  228. /*
  229. FetchEdgePart fetches part of a single edge from a partition of the graph.
  230. */
  231. func (gm *Manager) FetchEdgePart(part string, key string, kind string,
  232. attrs []string) (data.Edge, error) {
  233. // Get the HTrees which stores the edge
  234. edgeht, err := gm.getEdgeStorageHTree(part, kind, true)
  235. if err != nil || edgeht == nil {
  236. return nil, err
  237. }
  238. // Take reader lock
  239. gm.mutex.RLock()
  240. defer gm.mutex.RUnlock()
  241. // Read the edge from the datastore
  242. node, err := gm.readNode(key, kind, attrs, edgeht, edgeht)
  243. return data.NewGraphEdgeFromNode(node), err
  244. }
  245. /*
  246. StoreEdge stores a single edge in a partition of the graph. This function will
  247. overwrites any existing edge.
  248. */
  249. func (gm *Manager) StoreEdge(part string, edge data.Edge) error {
  250. // Check if the edge can be stored
  251. if err := gm.checkEdge(edge); err != nil {
  252. return err
  253. }
  254. // Get the HTrees which stores the edges and the edge index
  255. iht, err := gm.getEdgeIndexHTree(part, edge.Kind(), true)
  256. if err != nil {
  257. return err
  258. }
  259. edgeht, err := gm.getEdgeStorageHTree(part, edge.Kind(), true)
  260. if err != nil {
  261. return err
  262. }
  263. // Get the HTrees which stores the edge endpoints and make sure the endpoints
  264. // do exist
  265. end1nodeht, end1ht, err := gm.getNodeStorageHTree(part, edge.End1Kind(), false)
  266. if err != nil {
  267. return err
  268. } else if end1ht == nil {
  269. return &util.GraphError{
  270. Type: util.ErrInvalidData,
  271. Detail: "Can't store edge to non-existend node kind: " + edge.End1Kind(),
  272. }
  273. } else if end1, err := end1nodeht.Get([]byte(PrefixNSAttrs + edge.End1Key())); err != nil || end1 == nil {
  274. return &util.GraphError{
  275. Type: util.ErrInvalidData,
  276. Detail: fmt.Sprintf("Can't find edge endpoint: %s (%s)", edge.End1Key(), edge.End1Kind()),
  277. }
  278. }
  279. end2nodeht, end2ht, err := gm.getNodeStorageHTree(part, edge.End2Kind(), false)
  280. if err != nil {
  281. return err
  282. } else if end2ht == nil {
  283. return &util.GraphError{
  284. Type: util.ErrInvalidData,
  285. Detail: "Can't store edge to non-existend node kind: " + edge.End2Kind(),
  286. }
  287. } else if end2, err := end2nodeht.Get([]byte(PrefixNSAttrs + edge.End2Key())); err != nil || end2 == nil {
  288. return &util.GraphError{
  289. Type: util.ErrInvalidData,
  290. Detail: fmt.Sprintf("Can't find edge endpoint: %s (%s)", edge.End2Key(), edge.End2Kind()),
  291. }
  292. }
  293. // Take writer lock
  294. gm.mutex.Lock()
  295. defer gm.mutex.Unlock()
  296. // Write edge to the datastore
  297. oldedge, err := gm.writeEdge(edge, edgeht, end1ht, end2ht)
  298. if err != nil {
  299. return err
  300. }
  301. // Increase edge count if the edge was inserted and write the changes
  302. // to the index.
  303. if oldedge == nil {
  304. // Increase edge count
  305. currentCount := gm.EdgeCount(edge.Kind())
  306. if err := gm.writeEdgeCount(edge.Kind(), currentCount+1, true); err != nil {
  307. return err
  308. }
  309. // Write edge data to the index
  310. if iht != nil {
  311. if err := util.NewIndexManager(iht).Index(edge.Key(), edge.IndexMap()); err != nil {
  312. // The edge was written at this point and the model is
  313. // consistent only the index is missing entries
  314. return err
  315. }
  316. }
  317. } else if iht != nil {
  318. err := util.NewIndexManager(iht).Reindex(edge.Key(), edge.IndexMap(),
  319. oldedge.IndexMap())
  320. if err != nil {
  321. // The edge was written at this point and the model is
  322. // consistent only the index is missing entries
  323. return err
  324. }
  325. }
  326. // Execute rules
  327. trans := newInternalGraphTrans(gm)
  328. trans.subtrans = true
  329. var event int
  330. if oldedge == nil {
  331. event = EventEdgeCreated
  332. } else {
  333. event = EventEdgeUpdated
  334. }
  335. if err := gm.gr.graphEvent(trans, event, part, edge, oldedge); err != nil {
  336. return err
  337. } else if err := trans.Commit(); err != nil {
  338. return err
  339. }
  340. // Flush changes - errors only reported on the actual node storage flush
  341. gm.gs.FlushMain()
  342. gm.flushEdgeIndex(part, edge.Kind())
  343. gm.flushNodeStorage(part, edge.End1Kind())
  344. gm.flushNodeStorage(part, edge.End2Kind())
  345. return gm.flushEdgeStorage(part, edge.Kind())
  346. }
  347. /*
  348. writeEdge writes a given edge to the datastore. It is assumed that the caller
  349. holds the writer lock before calling the functions and that, after the function
  350. returns, the changes are flushed to the storage. The caller has also to ensure
  351. that the endpoints of the edge do exist. Returns the old edge if an
  352. update occurred.
  353. */
  354. func (gm *Manager) writeEdge(edge data.Edge, edgeTree *hash.HTree,
  355. end1Tree *hash.HTree, end2Tree *hash.HTree) (data.Edge, error) {
  356. // Create lookup keys
  357. spec1 := gm.nm.Encode16(edge.End1Role(), true) + gm.nm.Encode16(edge.Kind(), true) +
  358. gm.nm.Encode16(edge.End2Role(), true) + gm.nm.Encode16(edge.End2Kind(), true)
  359. spec2 := gm.nm.Encode16(edge.End2Role(), true) + gm.nm.Encode16(edge.Kind(), true) +
  360. gm.nm.Encode16(edge.End1Role(), true) + gm.nm.Encode16(edge.End1Kind(), true)
  361. specsNode1Key := PrefixNSSpecs + edge.End1Key()
  362. edgeInfo1Key := PrefixNSEdge + edge.End1Key() + spec1
  363. specsNode2Key := PrefixNSSpecs + edge.End2Key()
  364. edgeInfo2Key := PrefixNSEdge + edge.End2Key() + spec2
  365. // Function to insert a new spec into a specs map
  366. updateSpecMap := func(key string, spec string, tree *hash.HTree) error {
  367. var specsNode map[string]string
  368. obj, err := tree.Get([]byte(key))
  369. if err != nil {
  370. return err
  371. } else if obj == nil {
  372. specsNode = make(map[string]string)
  373. } else {
  374. specsNode = obj.(map[string]string)
  375. }
  376. specsNode[spec] = ""
  377. if _, err = tree.Put([]byte(key), specsNode); err != nil {
  378. return err
  379. }
  380. return nil
  381. }
  382. // Function to update the edgeTargetInfo entry
  383. updateTargetInfo := func(key string, endkey string, endkind string,
  384. cascadeToTarget bool, cascadeLastToTarget bool, cascadeFromTarget bool, cascadeLastFromTarget bool, tree *hash.HTree) error {
  385. var targetMap map[string]*edgeTargetInfo
  386. obj, err := tree.Get([]byte(key))
  387. if err != nil {
  388. return err
  389. } else if obj == nil {
  390. targetMap = make(map[string]*edgeTargetInfo)
  391. } else {
  392. targetMap = obj.(map[string]*edgeTargetInfo)
  393. }
  394. // Update the target info
  395. targetMap[edge.Key()] = &edgeTargetInfo{cascadeToTarget, cascadeLastToTarget,
  396. cascadeFromTarget, cascadeLastFromTarget, endkey, endkind}
  397. if _, err = tree.Put([]byte(key), targetMap); err != nil {
  398. return err
  399. }
  400. return nil
  401. }
  402. // Write node data for edge - if the data is incorrect we write the old
  403. // data back later. It is assumed that most of the time the data is correct
  404. // so we can avoid an extra read lookup
  405. var oldedge data.Edge
  406. if oldedgenode, err := gm.writeNode(edge, false, edgeTree, edgeTree, edgeAttributeFilter); err != nil {
  407. return nil, err
  408. } else if oldedgenode != nil {
  409. oldedge = data.NewGraphEdgeFromNode(oldedgenode)
  410. // Do a sanity check that the endpoints were not updated.
  411. if !data.NodeCompare(oldedge, edge, []string{data.EdgeEnd1Key,
  412. data.EdgeEnd1Kind, data.EdgeEnd1Role, data.EdgeEnd2Key,
  413. data.EdgeEnd2Kind, data.EdgeEnd2Role}) {
  414. // If the check fails then write back the old data and return
  415. // no error checking when writing back
  416. gm.writeNode(oldedge, false, edgeTree, edgeTree, edgeAttributeFilter)
  417. return nil, &util.GraphError{
  418. Type: util.ErrInvalidData,
  419. Detail: "Cannot update endpoints or spec of existing edge: " + edge.Key(),
  420. }
  421. }
  422. return oldedge, nil
  423. }
  424. // Create / update specs map on the nodes
  425. if err := updateSpecMap(specsNode1Key, spec1, end1Tree); err != nil {
  426. return nil, err
  427. }
  428. if err := updateSpecMap(specsNode2Key, spec2, end2Tree); err != nil {
  429. return nil, err
  430. }
  431. // Create / update the edgeInfo entries
  432. if err := updateTargetInfo(edgeInfo1Key, edge.End2Key(), edge.End2Kind(),
  433. edge.End1IsCascading(), edge.End1IsCascadingLast(), edge.End2IsCascading(),
  434. edge.End2IsCascadingLast(), end1Tree); err != nil {
  435. return nil, err
  436. }
  437. if err := updateTargetInfo(edgeInfo2Key, edge.End1Key(), edge.End1Kind(),
  438. edge.End2IsCascading(), edge.End2IsCascadingLast(),
  439. edge.End1IsCascading(), edge.End1IsCascadingLast(), end2Tree); err != nil {
  440. return nil, err
  441. }
  442. return nil, nil
  443. }
  444. /*
  445. RemoveEdge removes a single edge from a partition of the graph.
  446. */
  447. func (gm *Manager) RemoveEdge(part string, key string, kind string) (data.Edge, error) {
  448. // Get the HTrees which stores the edges and the edge index
  449. iht, err := gm.getEdgeIndexHTree(part, kind, true)
  450. if err != nil {
  451. return nil, err
  452. }
  453. edgeht, err := gm.getEdgeStorageHTree(part, kind, true)
  454. if err != nil {
  455. return nil, err
  456. }
  457. // Take writer lock
  458. gm.mutex.Lock()
  459. defer gm.mutex.Unlock()
  460. // Delete the node from the datastore
  461. node, err := gm.deleteNode(key, kind, edgeht, edgeht)
  462. edge := data.NewGraphEdgeFromNode(node)
  463. if err != nil {
  464. return edge, err
  465. }
  466. if node != nil {
  467. // Get the HTrees which stores the edge endpoints
  468. _, end1ht, err := gm.getNodeStorageHTree(part, edge.End1Kind(), false)
  469. if err != nil {
  470. return edge, err
  471. }
  472. _, end2ht, err := gm.getNodeStorageHTree(part, edge.End2Kind(), false)
  473. if err != nil {
  474. return edge, err
  475. }
  476. // Delete edge info from node storage
  477. if err := gm.deleteEdge(edge, end1ht, end2ht); err != nil {
  478. return edge, err
  479. }
  480. if iht != nil {
  481. err := util.NewIndexManager(iht).Deindex(key, edge.IndexMap())
  482. if err != nil {
  483. return edge, err
  484. }
  485. }
  486. // Decrease edge count
  487. currentCount := gm.EdgeCount(edge.Kind())
  488. if err := gm.writeEdgeCount(edge.Kind(), currentCount-1, true); err != nil {
  489. return edge, err
  490. }
  491. // Execute rules
  492. trans := newInternalGraphTrans(gm)
  493. trans.subtrans = true
  494. if err := gm.gr.graphEvent(trans, EventEdgeDeleted, part, edge); err != nil {
  495. return edge, err
  496. } else if err := trans.Commit(); err != nil {
  497. return edge, err
  498. }
  499. // Flush changes - errors only reported on the actual node storage flush
  500. gm.gs.FlushMain()
  501. gm.flushEdgeIndex(part, edge.Kind())
  502. gm.flushNodeStorage(part, edge.End1Kind())
  503. gm.flushNodeStorage(part, edge.End2Kind())
  504. return edge, gm.flushEdgeStorage(part, edge.Kind())
  505. }
  506. return nil, nil
  507. }
  508. /*
  509. Delete edge information from a given node storage
  510. */
  511. func (gm *Manager) deleteEdge(edge data.Edge, end1Tree *hash.HTree, end2Tree *hash.HTree) error {
  512. // Create lookup keys
  513. spec1 := gm.nm.Encode16(edge.End1Role(), true) + gm.nm.Encode16(edge.Kind(), true) +
  514. gm.nm.Encode16(edge.End2Role(), true) + gm.nm.Encode16(edge.End2Kind(), true)
  515. spec2 := gm.nm.Encode16(edge.End2Role(), true) + gm.nm.Encode16(edge.Kind(), true) +
  516. gm.nm.Encode16(edge.End1Role(), true) + gm.nm.Encode16(edge.End1Kind(), true)
  517. specsNode1Key := PrefixNSSpecs + edge.End1Key()
  518. edgeInfo1Key := PrefixNSEdge + edge.End1Key() + spec1
  519. specsNode2Key := PrefixNSSpecs + edge.End2Key()
  520. edgeInfo2Key := PrefixNSEdge + edge.End2Key() + spec2
  521. // Function to delete a spec from a specs map
  522. updateSpecMap := func(key string, spec string, tree *hash.HTree) error {
  523. var specsNode map[string]string
  524. obj, err := tree.Get([]byte(key))
  525. if err != nil {
  526. return &util.GraphError{Type: util.ErrReading, Detail: err.Error()}
  527. } else if obj == nil {
  528. return &util.GraphError{
  529. Type: util.ErrInvalidData,
  530. Detail: fmt.Sprintf("Expected spec entry is missing: %v", key),
  531. }
  532. } else {
  533. specsNode = obj.(map[string]string)
  534. }
  535. delete(specsNode, spec)
  536. if len(specsNode) == 0 {
  537. if _, err = tree.Remove([]byte(key)); err != nil {
  538. return err
  539. }
  540. } else if _, err = tree.Put([]byte(key), specsNode); err != nil {
  541. return err
  542. }
  543. return nil
  544. }
  545. // Function to delete the edgeTargetInfo entry
  546. updateTargetInfo := func(key string, tree *hash.HTree) (bool, error) {
  547. var targetMap map[string]*edgeTargetInfo
  548. obj, err := tree.Get([]byte(key))
  549. if err != nil {
  550. return false, &util.GraphError{Type: util.ErrReading, Detail: err.Error()}
  551. } else if obj == nil {
  552. return false, &util.GraphError{
  553. Type: util.ErrInvalidData,
  554. Detail: fmt.Sprintf("Expected edgeTargetInfo entry is missing: %v", key),
  555. }
  556. } else {
  557. targetMap = obj.(map[string]*edgeTargetInfo)
  558. }
  559. delete(targetMap, edge.Key())
  560. if len(targetMap) == 0 {
  561. if _, err = tree.Remove([]byte(key)); err != nil {
  562. return false, err
  563. }
  564. return true, nil
  565. } else if _, err = tree.Put([]byte(key), targetMap); err != nil {
  566. return false, err
  567. }
  568. return false, nil
  569. }
  570. // Remove the edgeInfo entries
  571. end1TargetInfoRemoved, err := updateTargetInfo(edgeInfo1Key, end1Tree)
  572. if err != nil {
  573. return err
  574. }
  575. end2TargetInfoRemoved, err := updateTargetInfo(edgeInfo2Key, end2Tree)
  576. if err != nil {
  577. return err
  578. }
  579. // Remove specs map on the nodes if the target info structure was removed
  580. if end1TargetInfoRemoved {
  581. if err := updateSpecMap(specsNode1Key, spec1, end1Tree); err != nil {
  582. return err
  583. }
  584. }
  585. if end2TargetInfoRemoved {
  586. if err := updateSpecMap(specsNode2Key, spec2, end2Tree); err != nil {
  587. return err
  588. }
  589. }
  590. return nil
  591. }
  592. /*
  593. Default filter function to filter out system edge attributes.
  594. */
  595. func edgeAttributeFilter(attr string) bool {
  596. return attr == data.NodeKey || attr == data.NodeKind
  597. }