[entropy.graph] implement Graph.destroy() to free circular references (was causing interesting memleak)
This commit is contained in:
@@ -385,6 +385,7 @@ def _revgraph_package(installed_pkg_id, package, dbconn, show_complete = False):
|
||||
_show_graph_legend()
|
||||
|
||||
del stack
|
||||
graph.destroy()
|
||||
del graph
|
||||
return 0
|
||||
|
||||
@@ -471,6 +472,7 @@ def _graph_package(match, package, entropy_intf, show_complete = False):
|
||||
_show_dependencies_legend()
|
||||
|
||||
del stack
|
||||
graph.destroy()
|
||||
del graph
|
||||
return 0
|
||||
|
||||
|
||||
@@ -1334,12 +1334,14 @@ class CalculatorsMixin:
|
||||
deptree_conflicts |= conflicts
|
||||
|
||||
if deps_not_found:
|
||||
graph.destroy()
|
||||
del graph
|
||||
raise DependenciesNotFound(deps_not_found)
|
||||
|
||||
# solve depgraph and append conflicts
|
||||
deptree = graph.solve()
|
||||
if 0 in deptree:
|
||||
graph.destroy()
|
||||
del graph
|
||||
raise KeyError("Graph contains a dep_level == 0")
|
||||
|
||||
@@ -1354,6 +1356,7 @@ class CalculatorsMixin:
|
||||
_colliding_deps = [x for x in _dup_deps_collisions.values() if \
|
||||
len(x) > 1]
|
||||
if _colliding_deps:
|
||||
graph.destroy()
|
||||
del graph
|
||||
raise DependenciesCollision(_colliding_deps)
|
||||
|
||||
@@ -1364,6 +1367,7 @@ class CalculatorsMixin:
|
||||
level_count += 1
|
||||
reverse_tree[level_count] = deptree[key]
|
||||
|
||||
graph.destroy()
|
||||
del deptree, graph
|
||||
reverse_tree[0] = deptree_conflicts
|
||||
|
||||
@@ -1660,6 +1664,7 @@ class CalculatorsMixin:
|
||||
deptree = graph.solve()
|
||||
del flat_dep_tree
|
||||
|
||||
graph.destroy()
|
||||
del graph
|
||||
|
||||
if self.xcache:
|
||||
|
||||
@@ -35,6 +35,25 @@ class GraphNode(object):
|
||||
self.__item = item
|
||||
self.__arches = set()
|
||||
|
||||
def __del__(self):
|
||||
try:
|
||||
self._clear()
|
||||
except (NameError, AttributeError):
|
||||
pass
|
||||
|
||||
def _clear(self):
|
||||
"""
|
||||
Clear the object
|
||||
"""
|
||||
try:
|
||||
self.__arches.clear()
|
||||
except (NameError, AttributeError):
|
||||
pass
|
||||
try:
|
||||
self.__item = None
|
||||
except (NameError, AttributeError):
|
||||
pass
|
||||
|
||||
def __str__(self):
|
||||
"""
|
||||
Default string representation.
|
||||
@@ -135,6 +154,22 @@ class GraphArchSet(object):
|
||||
self.__origin = starting_point
|
||||
self.__endpoints = set()
|
||||
|
||||
def __del__(self):
|
||||
try:
|
||||
self._clear()
|
||||
except (NameError, AttributeError):
|
||||
pass
|
||||
|
||||
def _clear(self):
|
||||
"""
|
||||
Cleanup the object
|
||||
"""
|
||||
try:
|
||||
self.__endpoints.clear()
|
||||
del self.__origin
|
||||
except (NameError, AttributeError):
|
||||
pass
|
||||
|
||||
def __str__(self):
|
||||
"""
|
||||
Default string representation.
|
||||
@@ -210,6 +245,16 @@ class TopologicalSorter(object):
|
||||
self.__adjacency_map = adjacency_map
|
||||
self.__stack = Lifo()
|
||||
|
||||
def __del__(self):
|
||||
try:
|
||||
self.__adjacency_map.clear()
|
||||
except (NameError, AttributeError):
|
||||
pass
|
||||
try:
|
||||
self.__stack.clear()
|
||||
except (NameError, AttributeError):
|
||||
pass
|
||||
|
||||
def __topological_sort_visit_node(self, node, low, result):
|
||||
"""
|
||||
Internal method, visits a node ad push to stack.
|
||||
@@ -340,6 +385,36 @@ class Graph(object):
|
||||
self.__archs_map = {}
|
||||
self.__graph_map_cache = None
|
||||
|
||||
def __del__(self):
|
||||
try:
|
||||
self.destroy()
|
||||
except (AttributeError, NameError):
|
||||
pass
|
||||
|
||||
def destroy(self):
|
||||
"""
|
||||
Cleanup any reference.
|
||||
"""
|
||||
try:
|
||||
for obj in self.__graph.values():
|
||||
obj._clear()
|
||||
self.__graph.clear()
|
||||
except (NameError, AttributeError):
|
||||
pass
|
||||
try:
|
||||
for obj in self.__archs_map.values():
|
||||
obj._clear()
|
||||
self.__archs_map.clear()
|
||||
except (NameError, AttributeError):
|
||||
pass
|
||||
try:
|
||||
if self.__graph_map_cache is not None:
|
||||
for obj in self.__graph_map_cache.values():
|
||||
obj._clear()
|
||||
self.__graph_map_cache.clear()
|
||||
except (NameError, AttributeError):
|
||||
pass
|
||||
|
||||
def __invalidate_cache(self):
|
||||
"""
|
||||
Private method, stay away from here.
|
||||
|
||||
Reference in New Issue
Block a user