You are viewing a plain text version of this content. The canonical link for it is here.
Posted to mod_python-commits@quetz.apache.org by gr...@apache.org on 2003/05/22 22:25:09 UTC
cvs commit: httpd-python/test/htdocs tests.py
grisha 2003/05/22 13:25:08
Modified: . CREDITS
Doc modpython4.tex
src requestobject.c
test test.py
test/htdocs tests.py
Log:
Added Conrad Steenberg's patch to provide sendfile functionality. Conrad's
patch was altered in that I used req.sendfile() instead of req.write_file()
because it seems a more intuitive name, and also the test case and
documentation is mine.
Submitted by: Conrad Steenberg
Revision Changes Path
1.18 +2 -0 httpd-python/CREDITS
Index: CREDITS
===================================================================
RCS file: /home/cvs/httpd-python/CREDITS,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -r1.17 -r1.18
--- CREDITS 10 Jan 2003 04:21:56 -0000 1.17
+++ CREDITS 22 May 2003 20:25:07 -0000 1.18
@@ -37,6 +37,8 @@
Sean Reifschneider <ja...@tummy.com>
+Conrad Steenberg <co...@hep.caltech.edu>
+
Chris Trengove <tr...@econdata.com.au>
Jarkko Torppa <to...@cute.fi>
1.31 +10 -0 httpd-python/Doc/modpython4.tex
Index: modpython4.tex
===================================================================
RCS file: /home/cvs/httpd-python/Doc/modpython4.tex,v
retrieving revision 1.30
retrieving revision 1.31
diff -u -r1.30 -r1.31
--- modpython4.tex 23 Jan 2003 22:34:18 -0000 1.30
+++ modpython4.tex 22 May 2003 20:25:07 -0000 1.31
@@ -623,6 +623,16 @@
\end{methoddesc}
+\begin{methoddesc}[request]{sendfile}{path\optional{, offset, len}}
+Sends \var{len} bytes of file \var{path} directly to the client,
+starting at offset \var{offset} using the server's internal
+API. \var{offset} defaults to 0, and \var{len} defaults to -1 (send
+the entire file).
+
+This function provides the most efficient way to send a file to the
+client.
+\end{methoddesc}
+
\begin{methoddesc}[request]{write}{string}
Writes \var{string} directly to the client, then flushes the buffer.
\end{methoddesc}
1.45 +46 -1 httpd-python/src/requestobject.c
Index: requestobject.c
===================================================================
RCS file: /home/cvs/httpd-python/src/requestobject.c,v
retrieving revision 1.44
retrieving revision 1.45
diff -u -r1.44 -r1.45
--- requestobject.c 7 Mar 2003 20:04:30 -0000 1.44
+++ requestobject.c 22 May 2003 20:25:07 -0000 1.45
@@ -807,6 +807,50 @@
}
+static PyObject * req_sendfile(requestobject *self, PyObject *args)
+{
+ char *fname;
+ apr_file_t *fd;
+ apr_size_t offset=0, len=-1, nbytes;
+ apr_status_t status;
+ PyObject * py_result = NULL;
+ apr_finfo_t finfo;
+
+ if (! PyArg_ParseTuple(args, "s|ll", &fname, &offset, &len))
+ return NULL; /* bad args */
+
+ status=apr_stat(&finfo, fname,
+ APR_READ, self->request_rec->pool);
+ if (status != APR_SUCCESS) {
+ PyErr_SetString(PyExc_IOError, "Could not stat file for reading");
+ return NULL;
+ }
+
+ status=apr_file_open(&fd, fname,
+ APR_READ, finfo.protection,
+ self->request_rec->pool);
+ if (status != APR_SUCCESS) {
+ PyErr_SetString(PyExc_IOError, "Could not open file for reading");
+ return NULL;
+ }
+
+ if (len==-1) len=finfo.size;
+
+ Py_BEGIN_ALLOW_THREADS
+ status = ap_send_fd(fd, self->request_rec, offset,
+ len, &nbytes);
+ Py_END_ALLOW_THREADS
+
+ if (status != APR_SUCCESS) {
+ PyErr_SetString(PyExc_IOError, "Write failed, client closed connection.");
+ return NULL;
+ }
+
+ py_result = PyLong_FromLong (nbytes);
+ Py_INCREF(py_result);
+ return py_result;
+}
+
static PyMethodDef request_methods[] = {
{"add_common_vars", (PyCFunction) req_add_common_vars, METH_NOARGS},
{"add_handler", (PyCFunction) req_add_handler, METH_VARARGS},
@@ -824,6 +868,7 @@
{"readlines", (PyCFunction) req_readlines, METH_VARARGS},
{"register_cleanup", (PyCFunction) req_register_cleanup, METH_VARARGS},
{"send_http_header", (PyCFunction) req_send_http_header, METH_NOARGS},
+ {"sendfile", (PyCFunction) req_sendfile, METH_VARARGS},
{"set_content_length", (PyCFunction) req_set_content_length, METH_VARARGS},
{"write", (PyCFunction) req_write, METH_VARARGS},
{ NULL, NULL } /* sentinel */
1.30 +27 -1 httpd-python/test/test.py
Index: test.py
===================================================================
RCS file: /home/cvs/httpd-python/test/test.py,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -r1.29 -r1.30
--- test.py 7 Mar 2003 20:04:31 -0000 1.29
+++ test.py 22 May 2003 20:25:07 -0000 1.30
@@ -241,6 +241,9 @@
IfModule("!mod_log_config.c",
LoadModule("log_config_module %s" %
self.quoteIfSpace(os.path.join(modpath, "mod_log_config.so")))),
+ IfModule("!mod_dir.c",
+ LoadModule("dir_module %s" %
+ self.quoteIfSpace(os.path.join(modpath, "mod_dir.so")))),
ServerRoot(SERVER_ROOT),
ErrorLog("logs/error_log"),
LogLevel("debug"),
@@ -599,6 +602,28 @@
if h != "test ok":
self.fail("x-test-header is there, but does not contain 'test ok'")
+ def test_req_sendfile_conf(self):
+
+ c = VirtualHost("*",
+ ServerName("test_req_sendfile"),
+ DocumentRoot(DOCUMENT_ROOT),
+ Directory(DOCUMENT_ROOT,
+ SetHandler("python-program"),
+ PythonHandler("tests::req_sendfile"),
+ PythonDebug("On")))
+
+ return str(c)
+
+ def test_req_sendfile(self):
+
+ print "\n * Testing req.sendfile()"
+
+ rsp = self.vhost_get("test_req_sendfile")
+
+ if (rsp != "test ok"):
+ self.fail("test failed")
+ conn = httplib.HTTPConnection("127.0.0.1:%s" % PORT)
+
def test_util_fieldstorage_conf(self):
c = VirtualHost("*",
@@ -840,6 +865,7 @@
perRequestSuite.addTest(PerRequestTestCase("test_req_readlines"))
perRequestSuite.addTest(PerRequestTestCase("test_req_register_cleanup"))
perRequestSuite.addTest(PerRequestTestCase("test_req_headers_out"))
+ perRequestSuite.addTest(PerRequestTestCase("test_req_sendfile"))
perRequestSuite.addTest(PerRequestTestCase("test_util_fieldstorage"))
perRequestSuite.addTest(PerRequestTestCase("test_postreadrequest"))
perRequestSuite.addTest(PerRequestTestCase("test_trans"))
1.27 +14 -1 httpd-python/test/htdocs/tests.py
Index: tests.py
===================================================================
RCS file: /home/cvs/httpd-python/test/htdocs/tests.py,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -r1.26 -r1.27
--- tests.py 7 Mar 2003 20:04:32 -0000 1.26
+++ tests.py 22 May 2003 20:25:07 -0000 1.27
@@ -658,6 +658,19 @@
return apache.OK
+def req_sendfile(req):
+
+ import tempfile
+ fname = tempfile.mktemp("txt")
+ f = open(fname, "w")
+ f.write(" test ok ");
+ f.close()
+
+ req.sendfile(fname, 2, 7)
+
+ os.remove(fname)
+ return apache.OK
+
def srv_register_cleanup(req):
req.cleanup_data = "test ok"
Re: cvs commit: httpd-python/test/htdocs tests.py
Posted by Greg Stein <gs...@lyra.org>.
On Thu, May 22, 2003 at 08:25:09PM -0000, grisha@apache.org wrote:
>...
> +++ requestobject.c 22 May 2003 20:25:07 -0000 1.45
> @@ -807,6 +807,50 @@
>
> }
>
> +static PyObject * req_sendfile(requestobject *self, PyObject *args)
> +{
> + char *fname;
> + apr_file_t *fd;
> + apr_size_t offset=0, len=-1, nbytes;
> + apr_status_t status;
> + PyObject * py_result = NULL;
> + apr_finfo_t finfo;
> +
> + if (! PyArg_ParseTuple(args, "s|ll", &fname, &offset, &len))
> + return NULL; /* bad args */
> +
> + status=apr_stat(&finfo, fname,
> + APR_READ, self->request_rec->pool);
> + if (status != APR_SUCCESS) {
> + PyErr_SetString(PyExc_IOError, "Could not stat file for reading");
> + return NULL;
> + }
> +
> + status=apr_file_open(&fd, fname,
> + APR_READ, finfo.protection,
> + self->request_rec->pool);
Ideally, you'd use Py_BEGIN/END_ALLOW_THREADS around these two APR calls.
Hitting the filesystem can "take a while", so allowing threads to run would
be a great thing.
>...
Cheers,
-g
--
Greg Stein, http://www.lyra.org/