Mercurial > p > roundup > code
diff roundup/cgi/client.py @ 4047:e70643990e9c
Support the use of sendfile() for file transfer, if available.
| author | Stefan Seefeld <stefan@seefeld.name> |
|---|---|
| date | Tue, 17 Feb 2009 04:32:34 +0000 |
| parents | 48be910ebda1 |
| children | 662cd78df973 |
line wrap: on
line diff
--- a/roundup/cgi/client.py Tue Feb 17 02:38:08 2009 +0000 +++ b/roundup/cgi/client.py Tue Feb 17 04:32:34 2009 +0000 @@ -819,10 +819,30 @@ "this file.") mime_type = klass.get(nodeid, 'type') - content = klass.get(nodeid, 'content') + + # If this object is a file (i.e., an instance of FileClass), + # see if we can find it in the filesystem. If so, we may be + # able to use the more-efficient request.sendfile method of + # sending the file. If not, just get the "content" property + # in the usual way, and use that. + content = None + filename = None + if isinstance(klass, hyperdb.FileClass): + try: + filename = self.db.filename(classname, nodeid) + except AttributeError: + # The database doesn't store files in the filesystem + # and therefore doesn't provide the "filename" method. + pass + except IOError: + # The file does not exist. + pass + if not filename: + content = klass.get(nodeid, 'content') + lmt = klass.get(nodeid, 'activity').timestamp() - self._serve_file(lmt, mime_type, content) + self._serve_file(lmt, mime_type, content, filename) def serve_static_file(self, file): ''' Serve up the file named from the templates dir @@ -853,21 +873,20 @@ else: mime_type = 'text/plain' - # snarf the content - f = open(filename, 'rb') - try: - content = f.read() - finally: - f.close() + self._serve_file(lmt, mime_type, '', filename) - self._serve_file(lmt, mime_type, content) - - def _serve_file(self, lmt, mime_type, content): + def _serve_file(self, lmt, mime_type, content=None, filename=None): ''' guts of serve_file() and serve_static_file() ''' + + if not content: + length = os.stat(filename)[stat.ST_SIZE] + else: + length = len(content) + # spit out headers self.additional_headers['Content-Type'] = mime_type - self.additional_headers['Content-Length'] = str(len(content)) + self.additional_headers['Content-Length'] = str(length) self.additional_headers['Last-Modified'] = rfc822.formatdate(lmt) ims = None @@ -884,7 +903,27 @@ if lmtt <= ims: raise NotModified - self.write(content) + if not self.headers_done: + self.header() + + if self.env['REQUEST_METHOD'] == 'HEAD': + return + + # If we have a file, and the 'sendfile' method is available, + # we can bypass reading and writing the content into application + # memory entirely. + if filename: + if hasattr(self.request, 'sendfile'): + self._socket_op(self.request.sendfile, filename) + return + f = open(filename, 'rb') + try: + content = f.read() + finally: + f.close() + + self._socket_op(self.request.wfile.write, content) + def renderContext(self): ''' Return a PageTemplate for the named page @@ -1059,6 +1098,7 @@ # and write self._socket_op(self.request.wfile.write, content) + def setHeader(self, header, value): '''Override a header to be returned to the user's browser. '''
