lib/utilrb/ruby_object_graph.rb
# Creates a BGL::Graph of ObjectRef objects which stores the current
# ruby object graph
#
# @param [Class] klass seed 
# @option options [Array<Object>] roots (nil) if given, the list of root
#   objects. Objects that are not referenced by one of these roots will
#   not be included in the final graph
Creates a BGL::Graph of ObjectRef objects which stores the current
ruby object graph
Creates a BGL :: Graph of ObjectRef objects which stores the current ruby object graph
def register_references_to(live_objects, options = Hash.new)
            orig_options = options 
            options = Kernel.validate_options options,
                :roots => [Object], :excluded_classes => [], :excluded_objects => [],
                :include_class_relation => false
            roots_class, roots = options[:roots].partition { |obj| obj.kind_of?(Class) }
            excluded_classes = options[:excluded_classes]
            excluded_objects = options[:excluded_objects]
            include_class_relation = options[:include_class_relation]
            desired_seeds = roots.map(&:object_id)
            excludes = [live_objects, self, graph, references, orig_options, options, roots, roots_class].to_value_set
            live_objects_total = live_objects.size
            live_objects.delete_if do |obj|
                if obj.kind_of?(DRbObject)
                    true
                elsif excludes.include?(obj) || obj.respond_to?(:__ruby_object_graph_internal__)
                    true
                else
                    references[obj.object_id] ||= ObjectRef.new(obj)
                    if roots_class.any? { |k| obj.kind_of?(k) }
                        if !excluded_classes.any? { |k| obj.kind_of?(k) }
                            if !excluded_objects.include?(obj)
                                desired_seeds << obj.object_id
                            end
                        end
                    end
                    false
                end
            end
            desired_seeds.each do |obj_id|
                graph.insert(references[obj_id])
            end
            ignored_enumeration = Hash.new
            names = Hash[
                :array => "Array",
                :value_set => "ValueSet[]",
                :vertex => "Vertex[]",
                :edge => "Edge[]",
                :hash_key => "Hash[key]",
                :hash_value => "Hash[value]",
                :proc => "Proc",
                :ancestor => "Ancestor"]
            puts "RubyObjectGraph: #{live_objects.size} objects found, #{desired_seeds.size} seeds and #{live_objects_total} total live objects"
            loop do
                old_graph_size = graph.size
                live_objects.each do |obj|
                    obj_ref = references[obj.object_id]
                    if include_class_relation
                        test_and_add_reference(obj_ref, obj.class, "class")
                    end
                    for var_name in obj.instance_variables
                        var = obj.instance_variable_get(var_name)
                        test_and_add_reference(obj_ref, var, var_name.to_s)
                    end
                    case obj
                    when Array
                        for var in obj
                            test_and_add_reference(obj_ref, var, names[:array])
                        end
                    when ValueSet
                        for var in obj
                            test_and_add_reference(obj_ref, var, names[:value_set])
                        end
                    when BGL::Graph
                        obj.each_vertex do
                            test_and_add_reference(obj_ref, var, names[:vertex])
                        end
                        obj.each_edge do |_, _, info|
                            test_and_add_reference(obj_ref, info, names[:edge])
                        end
                    when Hash
                        for var in obj
                            test_and_add_reference(obj_ref, var[0], names[:hash_key])
                            test_and_add_reference(obj_ref, var[1], names[:hash_value])
                        end
                    when Proc
                        if obj.respond_to?(:references)
                            for var in obj.references
                                begin
                                    test_and_add_reference(obj_ref, ObjectSpace._id2ref(var), names[:proc])
                                rescue RangeError
                                end
                            end
                        end
                    when Class
                        for ref in obj.ancestors
                            test_and_add_reference(obj_ref, ref, names[:ancestor])
                        end
                    else
                        if obj.respond_to?(:each)
                            if obj.kind_of?(Module) || obj.kind_of?(Class)
                                if !ignored_enumeration[obj]
                                    ignored_enumeration[obj] = true
                                    puts "ignoring enumerator class/module #{obj}"
                                end
                            else
                                if !ignored_enumeration[obj.class]
                                    ignored_enumeration[obj.class] = true
                                    puts "ignoring enumerator object of class #{obj.class}"
                                end
                            end
                        end
                    end
                end
                if old_graph_size == graph.size
                    break
                end
            end
            live_objects.clear 
            return graph
        end
def register_references_to ( live_objects , options = Hash . new ) orig_options = options options = Kernel . validate_options options , :roots => [ Object ] , :excluded_classes => [ ] , :excluded_objects => [ ] , :include_class_relation => false roots_class , roots = options [ :roots ] . partition { | obj | obj . kind_of? ( Class ) } excluded_classes = options [ :excluded_classes ] excluded_objects = options [ :excluded_objects ] include_class_relation = options [ :include_class_relation ] desired_seeds = roots . map ( & :object_id ) excludes = [ live_objects , self , graph , references , orig_options , options , roots , roots_class ] . to_value_set live_objects_total = live_objects . size live_objects . delete_if do | obj | if obj . kind_of? ( DRbObject ) true elsif excludes . include? ( obj ) || obj . respond_to? ( :__ruby_object_graph_internal__ ) true else references [ obj . object_id ] ||= ObjectRef . new ( obj ) if roots_class . any? { | k | obj . kind_of? ( k ) } if ! excluded_classes . any? { | k | obj . kind_of? ( k ) } if ! excluded_objects . include? ( obj ) desired_seeds << obj . object_id end end end false end end desired_seeds . each do | obj_id | graph . insert ( references [ obj_id ] ) end ignored_enumeration = Hash . new names = Hash [ :array => "Array" , :value_set => "ValueSet[]" , :vertex => "Vertex[]" , :edge => "Edge[]" , :hash_key => "Hash[key]" , :hash_value => "Hash[value]" , :proc => "Proc" , :ancestor => "Ancestor" ] puts "RubyObjectGraph: #{live_objects.size} objects found, #{desired_seeds.size} seeds and #{live_objects_total} total live objects" loop do old_graph_size = graph . size live_objects . each do | obj | obj_ref = references [ obj . object_id ] if include_class_relation test_and_add_reference ( obj_ref , obj . class , "class" ) end for var_name in obj . instance_variables var = obj . instance_variable_get ( var_name ) test_and_add_reference ( obj_ref , var , var_name . to_s ) end case obj when Array for var in obj test_and_add_reference ( obj_ref , var , names [ :array ] ) end when ValueSet for var in obj test_and_add_reference ( obj_ref , var , names [ :value_set ] ) end when BGL :: Graph obj . each_vertex do test_and_add_reference ( obj_ref , var , names [ :vertex ] ) end obj . each_edge do | _ , _ , info | test_and_add_reference ( obj_ref , info , names [ :edge ] ) end when Hash for var in obj test_and_add_reference ( obj_ref , var [ 0 ] , names [ :hash_key ] ) test_and_add_reference ( obj_ref , var [ 1 ] , names [ :hash_value ] ) end when Proc if obj . respond_to? ( :references ) for var in obj . references begin test_and_add_reference ( obj_ref , ObjectSpace . _id2ref ( var ) , names [ :proc ] ) rescue RangeError end end end when Class for ref in obj . ancestors test_and_add_reference ( obj_ref , ref , names [ :ancestor ] ) end else if obj . respond_to? ( :each ) if obj . kind_of? ( Module ) || obj . kind_of? ( Class ) if ! ignored_enumeration [ obj ] ignored_enumeration [ obj ] = true puts "ignoring enumerator class/module #{obj}" end else if ! ignored_enumeration [ obj . class ] ignored_enumeration [ obj . class ] = true puts "ignoring enumerator object of class #{obj.class}" end end end end end if old_graph_size == graph . size break end end live_objects . clear return graph end
Creates a BGL::Graph of ObjectRef objects which stores the current
ruby object graph
Creates a BGL :: Graph of ObjectRef objects which stores the current ruby object graph
# to exclude it from the graph # Create a single ObjectRef per (interesting) live object, so that we # can use a BGL::Graph to represent the reference graph.  This will be # what we are going to access later on. Use object IDs since we really # want to refer to objects and not use eql? comparisons # to avoid making it a central node in future calls
live_objects
<not_specific>
options
roots (nil) if given, the list of root objects. Objects that are not referenced by one of these roots will not be included in the final graph
roots ( nil ) if given the list of root objects . Objects that are not referenced by one of these roots will not be included in the final graph
new
<not_specific>
<not_specific>
None