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/