[Zope-Checkins] CVS: Zope/lib/python/ZServer - FTPResponse.py:1.14 FTPServer.py:1.31 HTTPResponse.py:1.45 Producers.py:1.10

Chris McDonough chrism at plope.com
Sun Mar 28 06:13:27 EST 2004


Update of /cvs-repository/Zope/lib/python/ZServer
In directory cvs.zope.org:/tmp/cvs-serv5691/lib/python/ZServer

Modified Files:
	FTPResponse.py FTPServer.py HTTPResponse.py Producers.py 
Log Message:
Merge chrism-publishfile-branch.  See http://dev.zope.org/Wikis/DevSite/Proposals/FasterStaticContentServing for more information.


=== Zope/lib/python/ZServer/FTPResponse.py 1.13 => 1.14 ===
--- Zope/lib/python/ZServer/FTPResponse.py:1.13	Tue Mar 18 16:15:14 2003
+++ Zope/lib/python/ZServer/FTPResponse.py	Sun Mar 28 06:12:56 2004
@@ -26,9 +26,6 @@
     """
 
     def __str__(self):
-#        return ZServerHTTPResponse.__str__(self)
-        # ZServerHTTPResponse.__str__(self) return HTTP headers
-        # Why should be send them to the FTP client ??? (ajung)
         return ''
 
     def outputBody(self):


=== Zope/lib/python/ZServer/FTPServer.py 1.30 => 1.31 ===
--- Zope/lib/python/ZServer/FTPServer.py:1.30	Wed Dec 31 14:45:35 2003
+++ Zope/lib/python/ZServer/FTPServer.py	Sun Mar 28 06:12:56 2004
@@ -310,7 +310,19 @@
         if status==200:
             self.make_xmit_channel()
             if not response._wrote:
-                self.client_dc.push(response.body)
+                # chrism: we explicitly use a large-buffered producer here to
+                # increase speed.  Using "client_dc.push" with the body causes
+                # a simple producer with a buffer size of 512 to be created
+                # to serve the data, and it's very slow
+                # (about 100 times slower than the large-buffered producer)
+                self.client_dc.push_with_producer(
+                    asynchat.simple_producer(response.body, 1<<16))
+                # chrism: if the response has a bodyproducer, it means that
+                # the actual body was likely an empty string.  This happens
+                # typically when someone returns a StreamIterator from
+                # Zope application code.
+                if response._bodyproducer:
+                    self.client_dc.push_with_producer(response._bodyproducer)
             else:
                 for producer in self._response_producers:
                     self.client_dc.push_with_producer(producer)
@@ -647,3 +659,4 @@
         # override asyncore limits for nt's listen queue size
         self.accepting = 1
         return self.socket.listen (num)
+


=== Zope/lib/python/ZServer/HTTPResponse.py 1.44 => 1.45 ===
--- Zope/lib/python/ZServer/HTTPResponse.py:1.44	Thu Jan 15 18:02:58 2004
+++ Zope/lib/python/ZServer/HTTPResponse.py	Sun Mar 28 06:12:56 2004
@@ -21,13 +21,14 @@
 from cStringIO import StringIO
 import thread
 from ZPublisher.HTTPResponse import HTTPResponse
+from ZPublisher.Iterators import IStreamIterator
 from medusa.http_date import build_http_date
 from PubCore.ZEvent import Wakeup
 from medusa.producers import hooked_producer
 from medusa import http_server
 import asyncore
 from Producers import ShutdownProducer, LoggingProducer, CallbackProducer, \
-    file_part_producer, file_close_producer
+    file_part_producer, file_close_producer, iterator_producer
 from types import LongType
 import DebugLogger
 
@@ -49,6 +50,7 @@
     _streaming=0
     # using chunking transfer-encoding
     _chunking=0
+    _bodyproducer = None
 
     def __str__(self,
                 html_search=re.compile('<html>',re.I).search,
@@ -230,6 +232,22 @@
         self._retried_response = response
         return response
 
+    def outputBody(self):
+        """Output the response body"""
+        self.stdout.write(str(self))
+        if self._bodyproducer:
+            self.stdout.write(self._bodyproducer, 0)
+
+    def setBody(self, body, title='', is_error=0, **kw):
+        """ Accept either a stream iterator or a string as the body """
+        if IStreamIterator.isImplementedBy(body):
+            assert(self.headers.has_key('content-length'))
+            # wrap the iterator up in a producer that medusa can understand
+            self._bodyproducer = iterator_producer(body)
+            HTTPResponse.setBody(self, '', title, is_error, **kw)
+            return self
+        else:
+            HTTPResponse.setBody(self, body, title, is_error, **kw)
 
 class ChannelPipe:
     """Experimental pipe from ZPublisher to a ZServer Channel.


=== Zope/lib/python/ZServer/Producers.py 1.9 => 1.10 ===
--- Zope/lib/python/ZServer/Producers.py:1.9	Tue Mar 18 16:15:14 2003
+++ Zope/lib/python/ZServer/Producers.py	Sun Mar 28 06:12:56 2004
@@ -19,14 +19,12 @@
 
 class ShutdownProducer:
     "shuts down medusa"
-
     def more(self):
         asyncore.close_all()
 
 
 class LoggingProducer:
     "logs request"
-
     def __init__(self, logger, bytes, method='log'):
         self.logger=logger
         self.bytes=bytes
@@ -40,7 +38,6 @@
 
 class CallbackProducer:
     "Performs a callback in the channel's thread"
-
     def __init__(self, callback):
         self.callback=callback
 
@@ -52,7 +49,6 @@
 
 class file_part_producer:
     "producer wrapper for part of a file[-like] objects"
-
     # match http_channel's outgoing buffer size
     out_buffer_size = 1<<16
 
@@ -91,7 +87,6 @@
 
         return data
 
-
 class file_close_producer:
     def __init__(self, file):
         self.file=file
@@ -102,3 +97,13 @@
             file.close()
             self.file=None
         return ''
+
+class iterator_producer:
+    def __init__(self, iterator):
+        self.iterator = iterator
+
+    def more(self):
+        try:
+            return self.iterator.next()
+        except StopIteration:
+            return ''




More information about the Zope-Checkins mailing list