Download Install Tutorial Docs FAQ Tools WikiLicense Team IRC Planet Involvement Shop Book

Changeset 1964

Show
Ignore:
Timestamp:
05/24/08 00:49:43
Author:
fumanchu
Message:

Initial broken foray into sendfile madness. The benchmark hangs for some odd reason.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/sendfile/cherrypy/_cptools.py

    r1960 r1964  
    156156     
    157157    def _wrapper(self, **kwargs): 
     158        """If self.callable returns True, turn off any other handler.""" 
    158159        if self.callable(**kwargs): 
    159160            cherrypy.request.handler = None 
  • branches/sendfile/cherrypy/_cpwsgi.py

    r1938 r1964  
    123123            s, h, b = _cperror.bare_error() 
    124124            self.iter_response = iter(b) 
     125         
     126        if isinstance(b, self.environ['wsgi.file_wrapper']): 
     127            self.file_response = b 
    125128     
    126129    def iredirect(self, path, query_string): 
     
    298301        so that any WSGI middleware in self.pipeline can run first. 
    299302        """ 
    300         return self.response_class(environ, start_response, self.cpapp) 
     303        r_iter = self.response_class(environ, start_response, self.cpapp) 
     304        if getattr(r_iter, 'file_response', None) is not None: 
     305            # Return the file_wrapper object directly instead 
     306            return r_iter.file_response 
     307        return r_iter 
    301308     
    302309    def __call__(self, environ, start_response): 
  • branches/sendfile/cherrypy/lib/static.py

    r1957 r1964  
    6868     
    6969    # Set Content-Length and use an iterable (file object) 
    70     #   this way CP won't load the whole file in memory 
     70    # this way CP won't load the whole file in memory 
     71    # (assuming response.stream is True and no other 
     72    # code collapses the body). 
    7173    c_len = st.st_size 
    7274    bodyfile = open(path, 'rb') 
     75    fw = getattr(cherrypy.request, 'wsgi_environ', {}).get('wsgi.file_wrapper') 
     76    if fw is not None: 
     77        # TODO: support Content-Range 
     78        response.headers['Content-Length'] = c_len 
     79        response.body = fw(bodyfile) 
     80        print ".", 
     81        return response.body 
    7382     
    7483    # HTTP/1.0 didn't have Range/Accept-Ranges headers, or the 206 code 
  • branches/sendfile/cherrypy/test/benchmark.py

    r1908 r1964  
    286286     
    287287    print 
    288     print ("Client Thread Report (1000 requests, 14 bytes via staticdir, " 
     288    print ("Client Thread Report (1000 requests, 1500 bytes via staticdir, " 
    289289           "%s server threads):" % cherrypy.server.thread_pool) 
    290     print_report(thread_report("%s/static/index.html" % SCRIPT_NAME)) 
    291      
    292     print 
    293     print ("Size Report (1000 requests, 50 client threads, " 
    294            "%s server threads):" % cherrypy.server.thread_pool) 
    295     print_report(size_report()) 
     290    print_report(thread_report("%s/static/index2.html" % SCRIPT_NAME)) 
     291     
     292#    print 
     293#    print ("Size Report (1000 requests, 50 client threads, " 
     294#           "%s server threads):" % cherrypy.server.thread_pool) 
     295#    print_report(size_report()) 
    296296 
    297297 
  • branches/sendfile/cherrypy/wsgiserver/__init__.py

    r1961 r1964  
    546546        response = self.wsgi_app(self.environ, self.start_response) 
    547547        try: 
    548             for chunk in response: 
    549                 # "The start_response callable must not actually transmit 
    550                 # the response headers. Instead, it must store them for the 
    551                 # server or gateway to transmit only after the first 
    552                 # iteration of the application return value that yields 
    553                 # a NON-EMPTY string, or upon the application's first 
    554                 # invocation of the write() callable." (PEP 333) 
    555                 if chunk: 
    556                     self.write(chunk) 
     548            if isinstance(response, FileWrapper) and hasattr(response, '_transmit'): 
     549                if not self.sent_headers: 
     550                    self.sent_headers = True 
     551                    self.send_headers() 
     552                    # TODO: support chunked write 
     553                response._transmit(self.wfile._sock) 
     554            else: 
     555                for chunk in response: 
     556                    # "The start_response callable must not actually transmit 
     557                    # the response headers. Instead, it must store them for the 
     558                    # server or gateway to transmit only after the first 
     559                    # iteration of the application return value that yields 
     560                    # a NON-EMPTY string, or upon the application's first 
     561                    # invocation of the write() callable." (PEP 333) 
     562                    if chunk: 
     563                        self.write(chunk) 
    557564        finally: 
    558565            if hasattr(response, "close"): 
     
    15401547        self.environ.update(ssl_environ) 
    15411548 
     1549class FileWrapper(object): 
     1550 
     1551    def __init__(self, filelike, blksize=8192): 
     1552        self.filelike = filelike 
     1553        self.blksize = blksize 
     1554     
     1555    def close(self): 
     1556        if hasattr(self.filelike, 'close'): 
     1557            self.filelike.close() 
     1558     
     1559    def __iter__(self): 
     1560        return self 
     1561     
     1562    def next(self): 
     1563        data = self.filelike.read(self.blksize) 
     1564        if data: 
     1565            return data 
     1566        raise StopIteration 
     1567#HTTPConnection.environ['wsgi.file_wrapper'] = FileWrapper 
     1568     
     1569try: 
     1570    import sendfile 
     1571except ImportError: 
     1572    pass 
     1573else: 
     1574    class SendFileWrapper(FileWrapper): 
     1575     
     1576        def _transmit(self, socket): 
     1577            fd = self.filelike.fileno() 
     1578            filelen = os.fstat(fd).st_size 
     1579            offset = 0 
     1580            while offset < filelen: 
     1581                try: 
     1582                    pos, sent = sendfile.sendfile( 
     1583                        socket.fileno(), fd, offset,  
     1584                        self.blksize) 
     1585                    offset += sent 
     1586                except socket.error, e: 
     1587                    if e.args[0] not in socket_errors_nonblocking: 
     1588                        raise 
     1589                    print format_exc() 
     1590#    HTTPConnection.environ['wsgi.file_wrapper'] = SendFileWrapper 
     1591 
     1592 

Hosted by WebFaction

Log in as guest/cpguest to create tickets