<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>lib/erma/event_monitor.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -4,6 +4,7 @@ module Erma
       self.attributes['name'] = AttributeHolder.new(name, false, false)
     end
 
+    # Returns the value for the attribute with the given key.
     def [](key)
       attributes[key].value
     end
@@ -12,6 +13,25 @@ module Erma
       @attributes ||= {}
     end
 
+    # True if the attribute for the given key is set on this Monitor.
+    def has_attribute?(key)
+      !! attributes[key]
+    end
+
+    # True if the attribute for the given key is locked.
+    def locked?(key)
+      attributes[key].locked?
+    end
+
+    # True if the attribute for the given key is marked as serializable.
+    def serializable?(key)
+      attributes[key].serializable?
+    end
+
+    def set(key, value)
+      self.attributes[key] = AttributeHolder.new(value, false, false)
+    end
+
     # Holds a Monitor attribute value and associated metadata.
     class AttributeHolder
       attr_reader :value
@@ -20,6 +40,24 @@ module Erma
         @serializable = serializable
         @locked = locked
       end
+
+      def serializable
+        @serializable = true
+        self
+      end
+
+      def serializable?
+        @serializable
+      end
+
+      def lock
+        @locked = true
+        self
+      end
+
+      def locked?
+        @locked
+      end
     end
   end
 end</diff>
      <filename>lib/erma/monitor.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,5 @@
 require 'singleton'
-require 'monitor.rb'
+require 'monitor'
 
 module Erma
   # The engine that controls basic correlation of monitors as they are collected
@@ -46,6 +46,16 @@ module Erma
       end
     end
 
+    # Shuts down the MonitoringEngine if it is running. After it is shutdown,
+    # the MonitoringEngine will be started up.
+    #
+    # *This method is not thread-safe.* Clients should take care to ensure
+    # that multithreaded access to this method is synchronized.
+    def restart
+      shutdown if running?
+      startup
+    end
+
     # A lifecycle method that initializes the Monitor. All monitor
     # implementations must call this methods before setting any attributes on
     # themselves.
@@ -54,8 +64,11 @@ module Erma
     # inherited and global attributes applied.
     def init_monitor(monitor)
       return unless processing?
+
       monitor.set(:created_at, Time.now).serializable.lock
       monitor.set(:thread_id, Thread.current.__id__).serializable.lock
+
+      inherit_attributes(monitor)
     end
 
     # A lifecycle method that notifies observing MonitorProcessors that a new
@@ -94,7 +107,12 @@ module Erma
     # before they call process().
     def composite_monitor_completed(monitor)
       return unless processing?
-      handle_monitor(monitor, :composite_monitor_completed)
+
+      return unless monitor_stack.include?(monitor)
+
+      while (missed_mon = monitor_stack.pop) != monitor
+        process(missed_mon)
+      end
     end
 
     # A lifecycle method that notifies observing MonitorProcessors that a
@@ -105,7 +123,16 @@ module Erma
       handle_monitor(monitor, :process)
     end
 
+    
+    # Obtains the first CompositeMonitor found on the per thread stack that has
+    # its name attribute equal to the supplied name. This method should be used
+    # in situations where stateless code is unable to hold a reference to
+    # the CompositeMonitor that was originally created. Supplying the name
+    # value is needed to ensure that instrumentation errors in code called by
+    # users of this method does not interfere with the ability to correctly
+    # obtain the original CompositeMonitor.
     def get_composite_monitor_named(name)
+      raise 'Must supply a non-nil name' if name.nil?
       monitor_stack.reverse.find {|m| m['name'] == name} 
     end
 
@@ -114,7 +141,16 @@ module Erma
     end
 
     def inheritable_attributes
-      @global_attributes
+      inheritable_attributes = {}
+      global_attributes.each do |key, value|
+        inheritable_attributes[key] = Erma::Monitor::AttributeHolder.new(value, false, false)
+      end
+
+      monitor_stack.each do |ancestor|
+        inheritable_attributes.merge!(ancestor.inheritable_attribute_holders)
+      end
+
+      inheritable_attributes
     end
 
     attr_writer :enabled
@@ -147,6 +183,12 @@ module Erma
       end
     end
 
+    def inherit_attributes(monitor)
+      global_attributes.each do |key, value|
+        monitor.set(key, value)
+      end
+    end
+
     def initialize
       self.enabled = true
     end</diff>
      <filename>lib/erma/monitoring_engine.rb</filename>
    </modified>
    <modified>
      <diff>@@ -7,3 +7,4 @@ module Erma; end
 
 require 'erma/monitoring_engine'
 require 'erma/monitor'
+require 'erma/event_monitor'</diff>
      <filename>lib/ermarb.rb</filename>
    </modified>
    <modified>
      <diff>@@ -5,11 +5,9 @@ describe Erma::MonitoringEngine do
     @engine = Erma::MonitoringEngine.instance
     @engine.enabled = true
     @engine.processor_factory = stub('MockProcessorFactory', :null_object =&gt; true)
-    @engine.startup
+    @engine.restart
   end
 
-  after { @engine.shutdown }
-
   it &quot;should be enabled after startup&quot; do
     @engine.startup
     @engine.should be_enabled
@@ -65,6 +63,24 @@ describe Erma::MonitoringEngine do
     @engine.should_not be_running
   end
 
+  describe &quot;restart&quot; do
+    it &quot;should call shutdown&quot; do
+      @engine.should_receive(:shutdown)
+      @engine.restart
+    end
+
+    it &quot;should not call shutdown if not running&quot; do
+      @engine.shutdown
+      @engine.should_receive(:shutdown).never
+      @engine.restart
+    end
+
+    it &quot;should call startup&quot; do
+      @engine.should_receive(:startup)
+      @engine.restart
+    end
+  end
+
   # TODO Java version should have this concept instead of confusing isEnabled() method
   describe &quot;processing?&quot; do
     it &quot;should be true if enabled and running&quot; do
@@ -148,29 +164,32 @@ describe Erma::MonitoringEngine do
 
   describe &quot;processing init_monitor callback&quot; do
     before do 
-      @monitor = stub_everything('mock_monitor')
+      @monitor = Erma::EventMonitor.new('test')
     end
 
     it &quot;should set the created_at attribute on the monitor as serializable and locked&quot; do
-      attr_holder = mock('attr_holder')
-      @monitor.should_receive(:set).with(:created_at, anything).and_return(attr_holder)
-      @monitor.should_receive(:set).with(:thread_id, anything).and_return(stub_everything)
-      attr_holder.should_receive(:serializable).and_return(attr_holder)
-      attr_holder.should_receive(:lock)
       @engine.init_monitor(@monitor)
+      @monitor.should have_attribute(:created_at)
+      @monitor.should be_locked(:created_at)
+      @monitor.should be_serializable(:created_at)
     end
 
     it &quot;should set the thread ID attribute on the monitor and serializable and locked&quot; do
-      attr_holder = mock('attr_holder')
-      @monitor.should_receive(:set).with(:created_at, anything).and_return(stub_everything)
-      @monitor.should_receive(:set).with(:thread_id, Thread.current.__id__).and_return(attr_holder)
-      attr_holder.should_receive(:serializable).and_return(attr_holder)
-      attr_holder.should_receive(:lock)
       @engine.init_monitor(@monitor)
+      @monitor.should have_attribute(:thread_id)
+      @monitor.should be_locked(:thread_id)
+      @monitor.should be_serializable(:thread_id)
+      @monitor[:thread_id].should == Thread.current.__id__
     end
 
     it &quot;should set inherited attributes on monitor&quot;
 
+    it &quot;should inherit global attributes&quot; do
+      @engine.global_attributes['foo'] = 10
+      @engine.init_monitor(@monitor)
+      @monitor['foo'].should == 10
+    end
+
     it &quot;should do nothing if not enabled&quot; do
       @engine.enabled = false
       @engine.init_monitor(mock('mock_monitor'))
@@ -212,23 +231,69 @@ describe Erma::MonitoringEngine do
   end
 
   describe &quot;processing composite_monitor_completed callback&quot; do
+    it &quot;should pop the monitor from the stack&quot; do
+      @monitor = Erma::Monitor.new('foo')
+      @engine.composite_monitor_started(@monitor)
+      @engine.composite_monitor_completed(@monitor)
+      @engine.get_composite_monitor_named('foo').should == nil
+    end
+
+    it &quot;should pop only the monitor provided&quot; do
+      @parent = Erma::Monitor.new('parent')
+      @child = Erma::Monitor.new('child')
+      @engine.composite_monitor_started(@parent)
+      @engine.composite_monitor_started(@child)
+      @engine.composite_monitor_completed(@child)
+      @engine.get_composite_monitor_named('child').should == nil
+      @engine.get_composite_monitor_named('parent').should == @parent
+    end
+
+    it &quot;should ignore double calls&quot; do
+      @parent = Erma::Monitor.new('parent')
+      @child = Erma::Monitor.new('child')
+      @engine.composite_monitor_started(@parent)
+      @engine.composite_monitor_started(@child)
+      @engine.composite_monitor_completed(@child)
+      @engine.composite_monitor_completed(@child)
+      @engine.get_composite_monitor_named('child').should == nil
+      @engine.get_composite_monitor_named('parent').should == @parent
+    end
+
+    it &quot;should process missed monitors&quot; do
+      @parent = Erma::Monitor.new('parent')
+      @child = Erma::Monitor.new('child')
+      @engine.should_receive(:process).with(@child)
+      @engine.composite_monitor_started(@parent)
+      @engine.composite_monitor_started(@child)
+      @engine.composite_monitor_completed(@parent)
+    end
+  end
+
+  describe &quot;get_composite_monitor_named&quot; do
+    it &quot;should raise a RuntimeError when passed nil&quot; do
+      lambda { @engine.get_composite_monitor_named(nil) }.should raise_error
+    end
   end
 
   describe &quot;global_attributes&quot; do
+    before do
+      @engine.global_attributes.clear
+    end
+
     it &quot;should be included in the inheritable_attributes call&quot; do
       @engine.global_attributes['foo'] = 12
-      @engine.inheritable_attributes['foo'].should == 12
+      @engine.inheritable_attributes['foo'].value.should == 12
     end
 
     it &quot;should be able to be overridden&quot; do
       @engine.global_attributes['foo'] = 12
       @engine.global_attributes['foo'] = 13
-      @engine.inheritable_attributes['foo'].should == 13
+      @engine.inheritable_attributes['foo'].value.should == 13
     end
 
     it &quot;should be global across threads&quot; do
       @engine.global_attributes['foo'] = 12
-      thread = Thread.new { @engine.inheritable_attributes['foo'].should == 12 }
+      thread = Thread.new { @engine.inheritable_attributes['foo'].value.should == 12 }
       thread.join
     end
   end
@@ -244,7 +309,6 @@ describe Erma::MonitoringEngine do
     end
 
     it &quot;should include inheritable attributes on parent Monitors&quot; do
-      pending
       @engine.inheritable_attributes.should == @attr_holders
     end
   end</diff>
      <filename>spec/monitoring_engine_spec.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>c665fd235d118902266f72ec704835a21f6b5d16</id>
    </parent>
  </parents>
  <author>
    <name>Doug Barth</name>
    <email>dougbarth@gmail.com</email>
  </author>
  <url>http://github.com/dougbarth/ermarb/commit/4053c8baafbf47b86bba884dbf34b24276c1010c</url>
  <id>4053c8baafbf47b86bba884dbf34b24276c1010c</id>
  <committed-date>2008-08-03T19:47:58-07:00</committed-date>
  <authored-date>2008-08-03T19:47:58-07:00</authored-date>
  <message>More porting work.</message>
  <tree>65b5fa988a19bedc7e5eb627c1cb6f8412a9931a</tree>
  <committer>
    <name>Doug Barth</name>
    <email>dougbarth@gmail.com</email>
  </committer>
</commit>
