Class: RubyBreaker::Runtime::Monitor

Inherits:
Object
  • Object
show all
Defined in:
lib/rubybreaker/runtime/monitor.rb

Overview

This class monitors method calls before and after. It simply reroutes the responsibility to the appropriate pluggable type system which does the actual work of gathering type information.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(pluggable) ⇒ Monitor

Returns a new instance of Monitor.



155
156
157
# File 'lib/rubybreaker/runtime/monitor.rb', line 155

def initialize(pluggable)
  @pluggable = pluggable
end

Instance Attribute Details

#pluggableObject

Returns the value of attribute pluggable.



32
33
34
# File 'lib/rubybreaker/runtime/monitor.rb', line 32

def pluggable
  @pluggable
end

Class Method Details

.get_alt_meth_name(meth_name) ⇒ Object

This method returns the alternative (renamed) method name



146
147
148
# File 'lib/rubybreaker/runtime/monitor.rb', line 146

def self.get_alt_meth_name(meth_name)
  return "__rubybreaker_#{meth_name}"
end

.get_orig_meth_name(meth_name) ⇒ Object

This method returns the original method name



151
152
153
# File 'lib/rubybreaker/runtime/monitor.rb', line 151

def self.get_orig_meth_name(meth_name)
  return meth_name[2..-1]
end

.route(route_type, obj, meth_name, *args, &blk) ⇒ Object

This will do the actual routing work for a particular “monitored” method call.

route_type

:break or :check

obj

is the object receiving the message; is never wrapped object

meth_name
is the original method name being called args

is a

list of arguments for the original method call blk

is the block

argument for the original method call

– NOTE: This method should not assume that obj is a monitored object. That is, no special method should be called to obj unless it checks first.



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/rubybreaker/runtime/monitor.rb', line 47

def self.route(route_type, obj, meth_name, *args, &blk)

  # remember the switch mode before turning it off
  switch = GLOBAL_MONITOR_SWITCH.switch

  # turn off the monitor so we do not fall into an infinite loop
  GLOBAL_MONITOR_SWITCH.turn_off()

  # use symbol instead of string throughout this code
  meth_name = :"#{meth_name}" 

  # first, get the context right
  # notice the argument 2 to the caller!
  #
  # CONTEXT.push(obj, meth_name, 
  #              Position.convert_caller_to_pos(caller(2)))
  CONTEXT.push(Position.convert_caller_to_pos(caller(2)))

  # this is what the renamed method
  stub_meth_name = get_alt_meth_name(meth_name) 

  RubyBreaker.log("Route to #{stub_meth_name}", :debug, CONTEXT)

  # short-circuit if switch was off--i.e., no monitoring
  if !switch
    retval = obj.send(stub_meth_name.to_sym,*args,&blk)
    CONTEXT.pop() # do not forget to pop the context before returning
    return retval
  end

  is_obj_mod = (obj.class == Class or obj.class == Module)
  mod = is_obj_mod ? Runtime.eigen_class(obj) : obj.class

  # mm = get_module_monitor(mod) unless is_obj_mod
  mm = MONITOR_MAP[mod] 

  # There is something wrong if there isn't a module monitor
  # associated with the call.
  # raise Exception if mm == nil || !mm.include?(meth_name)

  meth_info = MethodInfo.new(meth_name, args, blk, nil)

  begin
    case route_type
    when :break
      mm.break_before_method(obj, meth_info)
    when :check
      mm.check_before_method(obj, meth_info)
    end
  rescue ::Exception => e
    RubyBreaker.log("Exception #{e.class} has been raised.", :debug, CONTEXT)
    # Trap it, turn on the global monitor and then re-raise the
    # exception
    GLOBAL_MONITOR_SWITCH.turn_on()
    raise e
  end

  # we are going to turn the switch back on
  GLOBAL_MONITOR_SWITCH.turn_on()

  # call the original method which was renamed
  retval = obj.send(stub_meth_name.to_sym, *meth_info.args,
                    &meth_info.blk)

  # turn the switch off again
  GLOBAL_MONITOR_SWITCH.turn_off()

  # Remember the return value in the method info object.
  meth_info.ret = retval

  begin
    case route_type
    when :break
      mm.break_after_method(obj, meth_info)
    when :check
      mm.check_after_method(obj, meth_info)
    end
  rescue ::Exception => e
    # Trap it, turn on the global monitor and then re-raise the
    # exception
    RubyBreaker.log("Exception #{e.class} has been raised.", :debug, CONTEXT)
    GLOBAL_MONITOR_SWITCH.turn_on()
    raise e
  end

  retval = meth_info.ret  # Return value may have been altered by the
                          # after_method monitoring code

  # things are done in this context. pop it off.
  CONTEXT.pop()

  # it is always the case that the switch was off when this particular
  # call was made. (Otherwise, it would have quit somewhere above
  GLOBAL_MONITOR_SWITCH.turn_on() 

  return retval # always return the return value
end

Instance Method Details

#break_after_method(obj, meth_info) ⇒ Object

This method is invoked after the original method is executed.



175
176
177
# File 'lib/rubybreaker/runtime/monitor.rb', line 175

def break_after_method(obj, meth_info)
  @pluggable.break_after_method(obj, meth_info)
end

#break_before_method(obj, meth_info) ⇒ Object

This method is invoked before the original method is executed.



170
171
172
# File 'lib/rubybreaker/runtime/monitor.rb', line 170

def break_before_method(obj, meth_info)
  @pluggable.break_before_method(obj, meth_info)
end

#check_after_method(obj, meth_info) ⇒ Object

This method is invoked after the original method is executed.



165
166
167
# File 'lib/rubybreaker/runtime/monitor.rb', line 165

def check_after_method(obj, meth_info)
  @pluggable.check_after_method(obj, meth_info)
end

#check_before_method(obj, meth_info) ⇒ Object

This method is invoked before the original method is executed.



160
161
162
# File 'lib/rubybreaker/runtime/monitor.rb', line 160

def check_before_method(obj, meth_info)
  @pluggable.check_before_method(obj, meth_info)
end