about summary refs log tree commit homepage
diff options
context:
space:
mode:
-rw-r--r--Rakefile2
-rw-r--r--bin/mongrel_rails6
-rw-r--r--lib/mongrel.rb75
-rw-r--r--projects/mongrel_console/Rakefile2
-rw-r--r--test/test_http11.rb16
-rw-r--r--test/test_response.rb2
6 files changed, 77 insertions, 26 deletions
diff --git a/Rakefile b/Rakefile
index 4aeba02..dad9f7b 100644
--- a/Rakefile
+++ b/Rakefile
@@ -32,7 +32,7 @@ end
 setup_extension("http11", "http11")
 
 name="mongrel"
-version="0.3.11"
+version="0.3.12"
 
 setup_gem(name, version) do |spec|
   spec.summary = "A small fast HTTP library and server that runs Rails, Camping, and Nitro apps."
diff --git a/bin/mongrel_rails b/bin/mongrel_rails
index e66d99e..1682ae5 100644
--- a/bin/mongrel_rails
+++ b/bin/mongrel_rails
@@ -113,6 +113,12 @@ class Start < GemPlugin::Plugin "/commands"
         File.unlink @pid_file if File.exist?(@pid_file)
         @restart = true
       }
+
+      trap("INT") {
+        server.stop
+        File.unlink @pid_file if File.exist?(@pid_file)
+        @restart = false
+      }
     end
 
     # hook up any rails specific plugins
diff --git a/lib/mongrel.rb b/lib/mongrel.rb
index d5c994d..65d2f04 100644
--- a/lib/mongrel.rb
+++ b/lib/mongrel.rb
@@ -142,6 +142,40 @@ module Mongrel
       end
 
     end
+
+    def self.escape(s)
+      s.to_s.gsub(/([^ a-zA-Z0-9_.-]+)/n) {
+        '%'+$1.unpack('H2'*$1.size).join('%').upcase
+      }.tr(' ', '+')
+    end
+
+
+    def self.unescape(s)
+      s.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/n){
+        [$1.delete('%')].pack('H*')
+      }
+    end
+
+
+    def self.query_parse(qs, d = '&;')
+      params = {}
+      (qs||'').split(/[#{d}] */n).inject(params) { |h,p|
+        k, v=unescape(p).split('=',2)
+        if cur = params[k]
+          if cur.class == Array
+            params[k] << v
+          else
+            params[k] = [cur, v]
+          end
+        else
+          params[k] = v
+        end
+      }
+
+      return params
+    end
+
+    
   end
 
 
@@ -292,25 +326,11 @@ module Mongrel
     # try lowering it (after you've tuned your stuff of course).
     def initialize(host, port, num_processors=20, timeout=120)
       @socket = TCPServer.new(host, port)
-
       @classifier = URIClassifier.new
-      @req_queue = Queue.new
       @host = host
       @port = port
-      @processors = []
-
-      # create the worker threads
-      num_processors.times do |i|
-        @processors << Thread.new do
-          parser = HttpParser.new
-          while client = @req_queue.deq
-            Timeout::timeout(timeout) do
-              process_client(client, parser)
-              parser.reset
-            end
-          end
-        end
-      end
+      @worker_group = ThreadGroup.new
+      @timeout = timeout
 
     end
     
@@ -320,8 +340,9 @@ module Mongrel
     # the performance just does not improve.  It is currently carefully constructed
     # to make sure that it gets the best possible performance, but anyone who
     # thinks they can make it faster is more than welcome to take a crack at it.
-    def process_client(client, parser)
+    def process_client(client)
       begin
+        parser = HttpParser.new
         params = {}
 
         data = client.readpartial(Const::CHUNK_SIZE)
@@ -368,13 +389,22 @@ module Mongrel
     # Runs the thing.  It returns the thread used so you can "join" it.  You can also
     # access the HttpServer::acceptor attribute to get the thread later.
     def run
+      
       BasicSocket.do_not_reverse_lookup=true
+      
       @acceptor = Thread.new do
         Thread.current[:stopped] = false
-
+        
         while not Thread.current[:stopped]
           begin
-            @req_queue << @socket.accept
+            client = @socket.accept
+
+            thread = Thread.new do
+              process_client(client)
+            end
+          
+            thread.priority=1
+            @worker_group.add(thread)
           rescue StopServer
             STDERR.puts "Server stopped.  Exiting."
             @socket.close if not @socket.closed?
@@ -387,17 +417,14 @@ module Mongrel
 
         # now that processing is done we feed enough false onto the request queue to get
         # each processor to exit and stop processing.
-        @processors.length.times { @req_queue << false }
 
         # finally we wait until the queue is empty
-        while @req_queue.length > 0
-          STDERR.puts "Shutdown waiting for #{@req_queue.length} requests" if @req_queue.length > 0
+        while @worker_group.list.length > 0
+          STDERR.puts "Shutdown waiting for #{@worker_group.list.length} requests" if @worker_group.list.length > 0
           sleep 1
         end
       end
 
-      @acceptor.priority = 1
-
       return @acceptor
     end
 
diff --git a/projects/mongrel_console/Rakefile b/projects/mongrel_console/Rakefile
index 6193bad..f134b28 100644
--- a/projects/mongrel_console/Rakefile
+++ b/projects/mongrel_console/Rakefile
@@ -23,7 +23,7 @@ setup_gem(name, version) do |spec|
   spec.description = spec.summary
   spec.author="Zed A. Shaw"
   spec.add_dependency('gem_plugin', '>= 0.2.1')
-  spec.add_dependency('mongrel', '>= 0.2.1')
+  spec.add_dependency('mongrel', '>= 0.3.11')
   spec.files += Dir.glob("resources/**/*")
 end
 
diff --git a/test/test_http11.rb b/test/test_http11.rb
index 60d020b..6805039 100644
--- a/test/test_http11.rb
+++ b/test/test_http11.rb
@@ -1,6 +1,9 @@
 require 'test/unit'
 require 'http11'
+require 'mongrel'
+require 'benchmark'
 
+include Mongrel
 
 class HttpParserTest < Test::Unit::TestCase
     
@@ -34,5 +37,18 @@ class HttpParserTest < Test::Unit::TestCase
     assert !parser.finished?, "Parser shouldn't be finished"
     assert parser.error?, "Parser SHOULD have error"
   end
+
+  def test_query_parse
+    puts HttpRequest.query_parse("zed=1&frank=2").inspect
+    puts HttpRequest.query_parse("zed=1&zed=2&zed=3&frank=11;zed=45").inspect
+
+    puts Benchmark.measure {
+      10000.times do |i|
+        g = HttpRequest.query_parse("zed=1&zed=2&zed=3&frank=11").inspect
+      end
+    }        
+  end
+
+
 end
 
diff --git a/test/test_response.rb b/test/test_response.rb
index d436bfa..e905e01 100644
--- a/test/test_response.rb
+++ b/test/test_response.rb
@@ -1,5 +1,6 @@
 require 'test/unit'
 require 'mongrel'
+require 'benchmark'
 
 include Mongrel
 
@@ -40,5 +41,6 @@ class ResponseTest < Test::Unit::TestCase
     assert io.length > 0, "output didn't have data"
   end
 
+
 end