about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2011-10-12 14:00:23 -0700
committerEric Wong <normalperson@yhbt.net>2011-10-12 14:00:23 -0700
commitd5fc6f66bc17f27770b38126b6c4211fd938c5b5 (patch)
tree946d7be0f4f5aa57318abe220e354d6590519131
parent360b8569cbb2b795019db278463245cce4270d09 (diff)
downloadraindrops-d5fc6f66bc17f27770b38126b6c4211fd938c5b5.tar.gz
Just in case somebody tries to scan all addresses, we
won't run out of memory as easily.
-rw-r--r--lib/raindrops/watcher.rb30
-rw-r--r--test/test_watcher.rb14
2 files changed, 32 insertions, 12 deletions
diff --git a/lib/raindrops/watcher.rb b/lib/raindrops/watcher.rb
index 7683ed4..1f3aaf3 100644
--- a/lib/raindrops/watcher.rb
+++ b/lib/raindrops/watcher.rb
@@ -120,14 +120,14 @@ class Raindrops::Watcher
       end
     end
 
-    agg_class = opts[:agg_class] || Aggregate
-    start = Time.now.utc
-    @active = Hash.new { |h,k| h[k] = agg_class.new }
-    @queued = Hash.new { |h,k| h[k] = agg_class.new }
-    @resets = Hash.new { |h,k| h[k] = start }
-    @peak_active = Hash.new { |h,k| h[k] = Peak.new(start, start) }
-    @peak_queued = Hash.new { |h,k| h[k] = Peak.new(start, start) }
-    @snapshot = [ start, {} ]
+    @agg_class = opts[:agg_class] || Aggregate
+    @start_time = Time.now.utc
+    @active = Hash.new { |h,k| h[k] = @agg_class.new }
+    @queued = Hash.new { |h,k| h[k] = @agg_class.new }
+    @resets = Hash.new { |h,k| h[k] = @start_time }
+    @peak_active = Hash.new { |h,k| h[k] = Peak.new(@start_time, @start_time) }
+    @peak_queued = Hash.new { |h,k| h[k] = Peak.new(@start_time, @start_time) }
+    @snapshot = [ @start_time, {} ]
     @delay = opts[:delay] || 1
     @lock = Mutex.new
     @start = Mutex.new
@@ -186,19 +186,25 @@ class Raindrops::Watcher
     thr
   end
 
+  def non_existent_stats(time)
+    [ time, @start_time, @agg_class.new, 0, Peak.new(@start_time, @start_time) ]
+  end
+
   def active_stats(addr) # :nodoc:
     @lock.synchronize do
-      tmp, peak = @active[addr], @peak_active[addr]
       time, combined = @snapshot
-      [ time, @resets[addr], tmp.dup, combined[addr].active, peak ]
+      stats = combined[addr] or return non_existent_stats(time)
+      tmp, peak = @active[addr], @peak_active[addr]
+      [ time, @resets[addr], tmp.dup, stats.active, peak ]
     end
   end
 
   def queued_stats(addr) # :nodoc:
     @lock.synchronize do
-      tmp, peak = @queued[addr], @peak_queued[addr]
       time, combined = @snapshot
-      [ time, @resets[addr], tmp.dup, combined[addr].queued, peak ]
+      stats = combined[addr] or return non_existent_stats(time)
+      tmp, peak = @queued[addr], @peak_queued[addr]
+      [ time, @resets[addr], tmp.dup, stats.queued, peak ]
     end
   end
 
diff --git a/test/test_watcher.rb b/test/test_watcher.rb
index f22a954..056a3bf 100644
--- a/test/test_watcher.rb
+++ b/test/test_watcher.rb
@@ -43,6 +43,20 @@ class TestWatcher < Test::Unit::TestCase
     check_headers(resp.headers)
   end
 
+  def test_invalid
+    assert_nothing_raised do
+      @req.get("/active/666.666.666.666%3A666.txt")
+      @req.get("/queued/666.666.666.666%3A666.txt")
+      @req.get("/active/666.666.666.666%3A666.html")
+      @req.get("/queued/666.666.666.666%3A666.html")
+    end
+    addr = @app.instance_eval do
+      @peak_active.keys + @peak_queued.keys +
+         @resets.keys + @active.keys + @queued.keys
+    end
+    assert addr.grep(/666\.666\.666\.666/).empty?, addr.inspect
+  end
+
   def test_active_html
     resp = @req.get "/active/#@addr.html"
     assert_equal 200, resp.status.to_i