graphmanager_edges.go 21 KB

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