graphmanager_edges.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856
  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. trans := newInternalGraphTrans(gm)
  251. trans.subtrans = true
  252. err := gm.gr.graphEvent(trans, EventEdgeStore, part, edge)
  253. if err != nil {
  254. if err == ErrEventHandled {
  255. err = nil
  256. }
  257. return err
  258. }
  259. if err = trans.Commit(); err == nil {
  260. // Check if the edge can be stored
  261. if err := gm.checkEdge(edge); err != nil {
  262. return err
  263. }
  264. // Get the HTrees which stores the edges and the edge index
  265. iht, err := gm.getEdgeIndexHTree(part, edge.Kind(), true)
  266. if err != nil {
  267. return err
  268. }
  269. edgeht, err := gm.getEdgeStorageHTree(part, edge.Kind(), true)
  270. if err != nil {
  271. return err
  272. }
  273. // Get the HTrees which stores the edge endpoints and make sure the endpoints
  274. // do exist
  275. end1nodeht, end1ht, err := gm.getNodeStorageHTree(part, edge.End1Kind(), false)
  276. if err != nil {
  277. return err
  278. } else if end1ht == nil {
  279. return &util.GraphError{
  280. Type: util.ErrInvalidData,
  281. Detail: "Can't store edge to non-existing node kind: " + edge.End1Kind(),
  282. }
  283. } else if end1, err := end1nodeht.Get([]byte(PrefixNSAttrs + edge.End1Key())); err != nil || end1 == nil {
  284. return &util.GraphError{
  285. Type: util.ErrInvalidData,
  286. Detail: fmt.Sprintf("Can't find edge endpoint: %s (%s)", edge.End1Key(), edge.End1Kind()),
  287. }
  288. }
  289. end2nodeht, end2ht, err := gm.getNodeStorageHTree(part, edge.End2Kind(), false)
  290. if err != nil {
  291. return err
  292. } else if end2ht == nil {
  293. return &util.GraphError{
  294. Type: util.ErrInvalidData,
  295. Detail: "Can't store edge to non-existing node kind: " + edge.End2Kind(),
  296. }
  297. } else if end2, err := end2nodeht.Get([]byte(PrefixNSAttrs + edge.End2Key())); err != nil || end2 == nil {
  298. return &util.GraphError{
  299. Type: util.ErrInvalidData,
  300. Detail: fmt.Sprintf("Can't find edge endpoint: %s (%s)", edge.End2Key(), edge.End2Kind()),
  301. }
  302. }
  303. // Take writer lock
  304. gm.mutex.Lock()
  305. defer gm.mutex.Unlock()
  306. // Write edge to the datastore
  307. oldedge, err := gm.writeEdge(edge, edgeht, end1ht, end2ht)
  308. if err != nil {
  309. return err
  310. }
  311. // Increase edge count if the edge was inserted and write the changes
  312. // to the index.
  313. if oldedge == nil {
  314. // Increase edge count
  315. currentCount := gm.EdgeCount(edge.Kind())
  316. if err := gm.writeEdgeCount(edge.Kind(), currentCount+1, true); err != nil {
  317. return err
  318. }
  319. // Write edge data to the index
  320. if iht != nil {
  321. if err := util.NewIndexManager(iht).Index(edge.Key(), edge.IndexMap()); err != nil {
  322. // The edge was written at this point and the model is
  323. // consistent only the index is missing entries
  324. return err
  325. }
  326. }
  327. } else if iht != nil {
  328. err := util.NewIndexManager(iht).Reindex(edge.Key(), edge.IndexMap(),
  329. oldedge.IndexMap())
  330. if err != nil {
  331. // The edge was written at this point and the model is
  332. // consistent only the index is missing entries
  333. return err
  334. }
  335. }
  336. defer func() {
  337. // Flush changes - errors only reported on the actual node storage flush
  338. gm.gs.FlushMain()
  339. gm.flushEdgeIndex(part, edge.Kind())
  340. gm.flushNodeStorage(part, edge.End1Kind())
  341. gm.flushNodeStorage(part, edge.End2Kind())
  342. gm.flushEdgeStorage(part, edge.Kind())
  343. }()
  344. // Execute rules
  345. trans := newInternalGraphTrans(gm)
  346. trans.subtrans = true
  347. var event int
  348. if oldedge == nil {
  349. event = EventEdgeCreated
  350. } else {
  351. event = EventEdgeUpdated
  352. }
  353. if err := gm.gr.graphEvent(trans, event, part, edge, oldedge); err != nil && err != ErrEventHandled {
  354. return err
  355. } else if err := trans.Commit(); err != nil {
  356. return err
  357. }
  358. }
  359. return err
  360. }
  361. /*
  362. writeEdge writes a given edge to the datastore. It is assumed that the caller
  363. holds the writer lock before calling the functions and that, after the function
  364. returns, the changes are flushed to the storage. The caller has also to ensure
  365. that the endpoints of the edge do exist. Returns the old edge if an
  366. update occurred.
  367. */
  368. func (gm *Manager) writeEdge(edge data.Edge, edgeTree *hash.HTree,
  369. end1Tree *hash.HTree, end2Tree *hash.HTree) (data.Edge, error) {
  370. // Create lookup keys
  371. spec1 := gm.nm.Encode16(edge.End1Role(), true) + gm.nm.Encode16(edge.Kind(), true) +
  372. gm.nm.Encode16(edge.End2Role(), true) + gm.nm.Encode16(edge.End2Kind(), true)
  373. spec2 := gm.nm.Encode16(edge.End2Role(), true) + gm.nm.Encode16(edge.Kind(), true) +
  374. gm.nm.Encode16(edge.End1Role(), true) + gm.nm.Encode16(edge.End1Kind(), true)
  375. specsNode1Key := PrefixNSSpecs + edge.End1Key()
  376. edgeInfo1Key := PrefixNSEdge + edge.End1Key() + spec1
  377. specsNode2Key := PrefixNSSpecs + edge.End2Key()
  378. edgeInfo2Key := PrefixNSEdge + edge.End2Key() + spec2
  379. // Function to insert a new spec into a specs map
  380. updateSpecMap := func(key string, spec string, tree *hash.HTree) error {
  381. var specsNode map[string]string
  382. obj, err := tree.Get([]byte(key))
  383. if err != nil {
  384. return err
  385. } else if obj == nil {
  386. specsNode = make(map[string]string)
  387. } else {
  388. specsNode = obj.(map[string]string)
  389. }
  390. specsNode[spec] = ""
  391. if _, err = tree.Put([]byte(key), specsNode); err != nil {
  392. return err
  393. }
  394. return nil
  395. }
  396. // Function to update the edgeTargetInfo entry
  397. updateTargetInfo := func(key string, endkey string, endkind string,
  398. cascadeToTarget bool, cascadeLastToTarget bool, cascadeFromTarget bool, cascadeLastFromTarget bool, tree *hash.HTree) error {
  399. var targetMap map[string]*edgeTargetInfo
  400. obj, err := tree.Get([]byte(key))
  401. if err != nil {
  402. return err
  403. } else if obj == nil {
  404. targetMap = make(map[string]*edgeTargetInfo)
  405. } else {
  406. targetMap = obj.(map[string]*edgeTargetInfo)
  407. }
  408. // Update the target info
  409. targetMap[edge.Key()] = &edgeTargetInfo{cascadeToTarget, cascadeLastToTarget,
  410. cascadeFromTarget, cascadeLastFromTarget, endkey, endkind}
  411. if _, err = tree.Put([]byte(key), targetMap); err != nil {
  412. return err
  413. }
  414. return nil
  415. }
  416. // Write node data for edge - if the data is incorrect we write the old
  417. // data back later. It is assumed that most of the time the data is correct
  418. // so we can avoid an extra read lookup
  419. var oldedge data.Edge
  420. if oldedgenode, err := gm.writeNode(edge, false, edgeTree, edgeTree, edgeAttributeFilter); err != nil {
  421. return nil, err
  422. } else if oldedgenode != nil {
  423. oldedge = data.NewGraphEdgeFromNode(oldedgenode)
  424. // Do a sanity check that the endpoints were not updated.
  425. if !data.NodeCompare(oldedge, edge, []string{data.EdgeEnd1Key,
  426. data.EdgeEnd1Kind, data.EdgeEnd1Role, data.EdgeEnd2Key,
  427. data.EdgeEnd2Kind, data.EdgeEnd2Role}) {
  428. // If the check fails then write back the old data and return
  429. // no error checking when writing back
  430. gm.writeNode(oldedge, false, edgeTree, edgeTree, edgeAttributeFilter)
  431. return nil, &util.GraphError{
  432. Type: util.ErrInvalidData,
  433. Detail: "Cannot update endpoints or spec of existing edge: " + edge.Key(),
  434. }
  435. }
  436. return oldedge, nil
  437. }
  438. // Create / update specs map on the nodes
  439. if err := updateSpecMap(specsNode1Key, spec1, end1Tree); err != nil {
  440. return nil, err
  441. }
  442. if err := updateSpecMap(specsNode2Key, spec2, end2Tree); err != nil {
  443. return nil, err
  444. }
  445. // Create / update the edgeInfo entries
  446. if err := updateTargetInfo(edgeInfo1Key, edge.End2Key(), edge.End2Kind(),
  447. edge.End1IsCascading(), edge.End1IsCascadingLast(), edge.End2IsCascading(),
  448. edge.End2IsCascadingLast(), end1Tree); err != nil {
  449. return nil, err
  450. }
  451. if err := updateTargetInfo(edgeInfo2Key, edge.End1Key(), edge.End1Kind(),
  452. edge.End2IsCascading(), edge.End2IsCascadingLast(),
  453. edge.End1IsCascading(), edge.End1IsCascadingLast(), end2Tree); err != nil {
  454. return nil, err
  455. }
  456. return nil, nil
  457. }
  458. /*
  459. RemoveEdge removes a single edge from a partition of the graph.
  460. */
  461. func (gm *Manager) RemoveEdge(part string, key string, kind string) (data.Edge, error) {
  462. var err error
  463. trans := newInternalGraphTrans(gm)
  464. trans.subtrans = true
  465. if err = gm.gr.graphEvent(trans, EventEdgeDelete, part, key, kind); err != nil {
  466. if err == ErrEventHandled {
  467. err = nil
  468. }
  469. return nil, err
  470. }
  471. err = trans.Commit()
  472. if err == nil {
  473. // Get the HTrees which stores the edges and the edge index
  474. iht, err := gm.getEdgeIndexHTree(part, kind, true)
  475. if err != nil {
  476. return nil, err
  477. }
  478. edgeht, err := gm.getEdgeStorageHTree(part, kind, true)
  479. if err != nil {
  480. return nil, err
  481. }
  482. // Take writer lock
  483. gm.mutex.Lock()
  484. defer gm.mutex.Unlock()
  485. // Delete the node from the datastore
  486. node, err := gm.deleteNode(key, kind, edgeht, edgeht)
  487. edge := data.NewGraphEdgeFromNode(node)
  488. if err != nil {
  489. return edge, err
  490. }
  491. if node != nil {
  492. // Get the HTrees which stores the edge endpoints
  493. _, end1ht, err := gm.getNodeStorageHTree(part, edge.End1Kind(), false)
  494. if err != nil {
  495. return edge, err
  496. }
  497. _, end2ht, err := gm.getNodeStorageHTree(part, edge.End2Kind(), false)
  498. if err != nil {
  499. return edge, err
  500. }
  501. // Delete edge info from node storage
  502. if err := gm.deleteEdge(edge, end1ht, end2ht); err != nil {
  503. return edge, err
  504. }
  505. if iht != nil {
  506. err := util.NewIndexManager(iht).Deindex(key, edge.IndexMap())
  507. if err != nil {
  508. return edge, err
  509. }
  510. }
  511. // Decrease edge count
  512. currentCount := gm.EdgeCount(edge.Kind())
  513. if err := gm.writeEdgeCount(edge.Kind(), currentCount-1, true); err != nil {
  514. return edge, err
  515. }
  516. defer func() {
  517. // Flush changes - errors only reported on the actual node storage flush
  518. gm.gs.FlushMain()
  519. gm.flushEdgeIndex(part, edge.Kind())
  520. gm.flushNodeStorage(part, edge.End1Kind())
  521. gm.flushNodeStorage(part, edge.End2Kind())
  522. gm.flushEdgeStorage(part, edge.Kind())
  523. }()
  524. // Execute rules
  525. trans := newInternalGraphTrans(gm)
  526. trans.subtrans = true
  527. if err := gm.gr.graphEvent(trans, EventEdgeDeleted, part, edge); err != nil && err != ErrEventHandled {
  528. return edge, err
  529. } else if err := trans.Commit(); err != nil {
  530. return edge, err
  531. }
  532. return edge, nil
  533. }
  534. }
  535. return nil, err
  536. }
  537. /*
  538. Delete edge information from a given node storage
  539. */
  540. func (gm *Manager) deleteEdge(edge data.Edge, end1Tree *hash.HTree, end2Tree *hash.HTree) error {
  541. // Create lookup keys
  542. spec1 := gm.nm.Encode16(edge.End1Role(), true) + gm.nm.Encode16(edge.Kind(), true) +
  543. gm.nm.Encode16(edge.End2Role(), true) + gm.nm.Encode16(edge.End2Kind(), true)
  544. spec2 := gm.nm.Encode16(edge.End2Role(), true) + gm.nm.Encode16(edge.Kind(), true) +
  545. gm.nm.Encode16(edge.End1Role(), true) + gm.nm.Encode16(edge.End1Kind(), true)
  546. specsNode1Key := PrefixNSSpecs + edge.End1Key()
  547. edgeInfo1Key := PrefixNSEdge + edge.End1Key() + spec1
  548. specsNode2Key := PrefixNSSpecs + edge.End2Key()
  549. edgeInfo2Key := PrefixNSEdge + edge.End2Key() + spec2
  550. // Function to delete a spec from a specs map
  551. updateSpecMap := func(key string, spec string, tree *hash.HTree) error {
  552. var specsNode map[string]string
  553. obj, err := tree.Get([]byte(key))
  554. if err != nil {
  555. return &util.GraphError{Type: util.ErrReading, Detail: err.Error()}
  556. } else if obj == nil {
  557. return &util.GraphError{
  558. Type: util.ErrInvalidData,
  559. Detail: fmt.Sprintf("Expected spec entry is missing: %v", key),
  560. }
  561. } else {
  562. specsNode = obj.(map[string]string)
  563. }
  564. delete(specsNode, spec)
  565. if len(specsNode) == 0 {
  566. if _, err = tree.Remove([]byte(key)); err != nil {
  567. return err
  568. }
  569. } else if _, err = tree.Put([]byte(key), specsNode); err != nil {
  570. return err
  571. }
  572. return nil
  573. }
  574. // Function to delete the edgeTargetInfo entry
  575. updateTargetInfo := func(key string, tree *hash.HTree) (bool, error) {
  576. var targetMap map[string]*edgeTargetInfo
  577. obj, err := tree.Get([]byte(key))
  578. if err != nil {
  579. return false, &util.GraphError{Type: util.ErrReading, Detail: err.Error()}
  580. } else if obj == nil {
  581. return false, &util.GraphError{
  582. Type: util.ErrInvalidData,
  583. Detail: fmt.Sprintf("Expected edgeTargetInfo entry is missing: %v", key),
  584. }
  585. } else {
  586. targetMap = obj.(map[string]*edgeTargetInfo)
  587. }
  588. delete(targetMap, edge.Key())
  589. if len(targetMap) == 0 {
  590. if _, err = tree.Remove([]byte(key)); err != nil {
  591. return false, err
  592. }
  593. return true, nil
  594. } else if _, err = tree.Put([]byte(key), targetMap); err != nil {
  595. return false, err
  596. }
  597. return false, nil
  598. }
  599. // Remove the edgeInfo entries
  600. end1TargetInfoRemoved, err := updateTargetInfo(edgeInfo1Key, end1Tree)
  601. if err != nil {
  602. return err
  603. }
  604. end2TargetInfoRemoved, err := updateTargetInfo(edgeInfo2Key, end2Tree)
  605. if err != nil {
  606. return err
  607. }
  608. // Remove specs map on the nodes if the target info structure was removed
  609. if end1TargetInfoRemoved {
  610. if err := updateSpecMap(specsNode1Key, spec1, end1Tree); err != nil {
  611. return err
  612. }
  613. }
  614. if end2TargetInfoRemoved {
  615. if err := updateSpecMap(specsNode2Key, spec2, end2Tree); err != nil {
  616. return err
  617. }
  618. }
  619. return nil
  620. }
  621. /*
  622. Default filter function to filter out system edge attributes.
  623. */
  624. func edgeAttributeFilter(attr string) bool {
  625. return attr == data.NodeKey || attr == data.NodeKind
  626. }