class RubyBreaker::Runtime::Monitor

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.

Attributes

pluggable[RW]

Public Class Methods

get_alt_meth_name(meth_name) click to toggle source

This method returns the alternative (renamed) method name

# 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) click to toggle source

This method returns the original method name

# File lib/rubybreaker/runtime/monitor.rb, line 151
def self.get_orig_meth_name(meth_name)
  return meth_name[2..-1]
end
new(pluggable) click to toggle source
# File lib/rubybreaker/runtime/monitor.rb, line 155
def initialize(pluggable)
  @pluggable = pluggable
end
route(route_type, obj, meth_name, *args, &blk) click to toggle source

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

# 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

Public Instance Methods

break_after_method(obj, meth_info) click to toggle source

This method is invoked after the original method is executed.

# 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) click to toggle source

This method is invoked before the original method is executed.

# 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) click to toggle source

This method is invoked after the original method is executed.

# 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) click to toggle source

This method is invoked before the original method is executed.

# File lib/rubybreaker/runtime/monitor.rb, line 160
def check_before_method(obj, meth_info)
  @pluggable.check_before_method(obj, meth_info)
end