this patch:
- implements a typemap entry and a conversion function for apr_os_file_t
from perl glob
- implements send_fd

Tested with 5.6.1 and bleadperl

APR Issues:
- apr requires the length of the file to be sent as an arg to ap_send_fd
which makes it impossible to use with just opened fh. I don't know what to
do here, it'll break existing code.

Patch issues:
- I'm not sure whether I've to dup in mpxs_Apache__RequestRec_send_fd, and
whether I need to add dup in modperl_xs_sv2apr_os_file. I'm a little bit
confused when dup should be done and when not. Currently I had to
SvREFCNT_inc(in) in modperl_xs_sv2apr_os_file, or there is core dump on
the function mpxs_Apache__RequestRec_send_fd return. I know that we want
to make sure that the handle that we hold is valid, so to be safe should
we always dup when moving between APR and Perl?

- I wanted to implement modperl_xs_sv2apr_os_file and not to do the
XS work in mpxs_Apache__RequestRec_send_fd because we can re-use it
later, but I've an issue with the pool, because I need to malloc
apr_os_file_t *os_file in modperl_xs_sv2apr_os_file. Or is there another
way to return a reference to a variable from the function, that created
this variable?

- I'm also not sure whether I've picked the right name for APR::OS_File.

Index: xs/maps/apr_types.map
===================================================================
RCS file: /home/cvs/modperl-2.0/xs/maps/apr_types.map,v
retrieving revision 1.10
diff -u -r1.10 apr_types.map
--- xs/maps/apr_types.map       2001/09/17 00:38:07     1.10
+++ xs/maps/apr_types.map       2001/12/20 22:02:58
@@ -57,7 +57,7 @@

 #file stuff
 struct apr_file_t        | UNDEFINED
-struct apr_os_file_t     | UNDEFINED
+struct apr_os_file_t     | APR::OS_File
 struct apr_dir_t         | UNDEFINED
 struct apr_os_dir_t      | UNDEFINED
 apr_seek_where_t         | UNDEFINED
Index: xs/maps/modperl_functions.map
===================================================================
RCS file: /home/cvs/modperl-2.0/xs/maps/modperl_functions.map,v
retrieving revision 1.31
diff -u -r1.31 modperl_functions.map
--- xs/maps/modperl_functions.map       2001/12/20 18:12:16     1.31
+++ xs/maps/modperl_functions.map       2001/12/20 22:02:58
@@ -31,6 +31,7 @@
  apr_size_t:DEFINE_PRINTF | | ...
  SV *:DEFINE_BINMODE  | | request_rec *:r
  mpxs_Apache__RequestRec_sendfile | | r, filename=r->filename, offset=0, len=0
+ mpxs_Apache__RequestRec_send_fd | | r, fd, length
  mpxs_Apache__RequestRec_read | | r, buffer, bufsiz, offset=0
  long:DEFINE_READ | | request_rec *:r, SV *:buffer, int:bufsiz, int:offset=0
  mpxs_Apache__RequestRec_write | | r, buffer, bufsiz=-1, offset=0
Index: lib/Apache/compat.pm
===================================================================
RCS file: /home/cvs/modperl-2.0/lib/Apache/compat.pm,v
retrieving revision 1.32
diff -u -r1.32 compat.pm
--- lib/Apache/compat.pm        2001/12/20 01:31:24     1.32
+++ lib/Apache/compat.pm        2001/12/20 22:02:59
@@ -236,40 +236,6 @@
     $line ? $line : undef;
 }

-use constant IOBUFSIZE => 8192;
-
-#XXX: howto convert PerlIO to apr_file_t
-#so we can use the real ap_send_fd function
-#2.0 ap_send_fd() also has an additional offset parameter
-
-sub send_fd_length {
-    my($r, $fh, $length) = @_;
-
-    my $buff;
-    my $total_bytes_sent = 0;
-    my $len;
-
-    return 0 if $length == 0;
-
-    if (($length > 0) && ($total_bytes_send + IOBUFSIZE) > $length) {
-        $len = $length - $total_bytes_sent;
-    }
-    else {
-        $len = IOBUFSIZE;
-    }
-
-    while (read($fh, $buff, $len)) {
-        $total_bytes_sent += $r->puts($buff);
-    }
-
-    $total_bytes_sent;
-}
-
-sub send_fd {
-    my($r, $fh) = @_;
-    $r->send_fd_length($fh, -1);
-}
-
 package Apache::File;

 use Fcntl ();
Index: lib/ModPerl/WrapXS.pm
===================================================================
RCS file: /home/cvs/modperl-2.0/lib/ModPerl/WrapXS.pm,v
retrieving revision 1.39
diff -u -r1.39 WrapXS.pm
--- lib/ModPerl/WrapXS.pm       2001/12/14 05:12:13     1.39
+++ lib/ModPerl/WrapXS.pm       2001/12/20 22:02:59
@@ -511,6 +511,7 @@
 my %typemap = (
     'Apache::RequestRec' => 'T_APACHEOBJ',
     'apr_time_t' => 'T_APR_TIME',
+    'APR::OS_File' => 'T_APR_OS_FILE',
     'APR::Table' => 'T_HASHOBJ',
 );

Index: src/modules/perl/modperl_util.c
===================================================================
RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_util.c,v
retrieving revision 1.32
diff -u -r1.32 modperl_util.c
--- src/modules/perl/modperl_util.c     2001/12/14 04:35:28     1.32
+++ src/modules/perl/modperl_util.c     2001/12/20 22:02:59
@@ -138,6 +138,28 @@
     return NULL;
 }

+apr_os_file_t *modperl_xs_sv2apr_os_file(pTHX_ SV *in)
+{
+    /* XXX: how to get the pool? */
+    apr_os_file_t *os_file = apr_palloc(modperl_global_get_pconf(), 
+sizeof(apr_os_file_t *));
+    PerlIO *f;
+
+    if (in == &PL_sv_undef || !SvROK(in) ) {
+        Perl_croak(aTHX_ "panic: expecting file glob");
+    }
+
+    /* XXX: dumps core without this? leak with _inc? */
+    SvREFCNT_inc(in);
+    f = IoIFP(sv_2io(in));
+    if (!f) {
+        Perl_croak(aTHX_ "cannot retrieve PerlIO");
+    }
+
+    *os_file = (apr_os_file_t)PerlIO_fileno(f);
+    return os_file;
+}
+
+
 MP_INLINE SV *modperl_newSVsv_obj(pTHX_ SV *stashsv, SV *obj)
 {
     SV *newobj;
Index: src/modules/perl/modperl_util.h
===================================================================
RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_util.h,v
retrieving revision 1.31
diff -u -r1.31 modperl_util.h
--- src/modules/perl/modperl_util.h     2001/12/14 04:35:28     1.31
+++ src/modules/perl/modperl_util.h     2001/12/20 22:02:59
@@ -55,6 +55,8 @@

 request_rec *modperl_xs_sv2request_rec(pTHX_ SV *sv, char *classname, CV *cv);

+apr_os_file_t *modperl_xs_sv2apr_os_file(pTHX_ SV *in);
+
 MP_INLINE SV *modperl_newSVsv_obj(pTHX_ SV *stashsv, SV *obj);

 MP_INLINE SV *modperl_ptr2obj(pTHX_ char *classname, void *ptr);
Index: t/api/send_fd.t
===================================================================
RCS file: /home/cvs/modperl-2.0/t/api/send_fd.t,v
retrieving revision 1.3
diff -u -r1.3 send_fd.t
--- t/api/send_fd.t     2001/12/20 03:54:41     1.3
+++ t/api/send_fd.t     2001/12/20 22:02:59
@@ -4,6 +4,7 @@
 use Test;
 use Apache::Test ();
 use Apache::TestRequest;
+use Apache::TestUtil;

 plan tests => 3;

@@ -17,7 +18,9 @@

 my $module = 'response/TestAPI/send_fd.pm';

-ok length($data) == -s $module;
+ok t_cmp(-s $module,
+         length($data),
+         "send_fd sent bytes");

 $data = GET_BODY("$url?noexist.txt");

Index: t/response/TestAPI/send_fd.pm
===================================================================
RCS file: /home/cvs/modperl-2.0/t/response/TestAPI/send_fd.pm,v
retrieving revision 1.1
diff -u -r1.1 send_fd.pm
--- t/response/TestAPI/send_fd.pm       2001/04/28 19:29:43     1.1
+++ t/response/TestAPI/send_fd.pm       2001/12/20 22:02:59
@@ -3,20 +3,24 @@
 use strict;
 use warnings FATAL => 'all';

-use Apache::compat ();
-
 sub handler {
     my $r = shift;

     my $file = $r->args || __FILE__;

     open my $fh, $file or return Apache::NOT_FOUND;
+
+    my $size = -s $file;
+
+    return Apache::SERVER_ERROR unless $size;

-    my $bytes = $r->send_fd($fh);
+    my $bytes = $r->send_fd($fh, $size);

-    return Apache::SERVER_ERROR unless $bytes == -s $file;
+    # XXX: how to set the errno? so there will be a message in the log
+    # file
+    return Apache::SERVER_ERROR unless $bytes == $size;

-    Apache::OK;
+    return Apache::OK;
 }

 1;
Index: xs/typemap
===================================================================
RCS file: /home/cvs/modperl-2.0/xs/typemap,v
retrieving revision 1.5
diff -u -r1.5 typemap
--- xs/typemap  2001/09/25 19:44:03     1.5
+++ xs/typemap  2001/12/20 22:02:59
@@ -39,3 +39,6 @@

 T_CONST_CHAR_LEN
         $var = (const char *)SvPV($arg, ${var}_len)
+
+T_APR_OS_FILE
+        $var = modperl_xs_sv2apr_os_file(aTHX_ $arg)
\ No newline at end of file
Index: xs/Apache/RequestIO/Apache__RequestIO.h
===================================================================
RCS file: /home/cvs/modperl-2.0/xs/Apache/RequestIO/Apache__RequestIO.h,v
retrieving revision 1.23
diff -u -r1.23 Apache__RequestIO.h
--- xs/Apache/RequestIO/Apache__RequestIO.h     2001/12/20 18:12:15     1.23
+++ xs/Apache/RequestIO/Apache__RequestIO.h     2001/12/20 22:02:59
@@ -235,3 +235,26 @@

     return status;
 }
+
+static MP_INLINE
+apr_size_t mpxs_Apache__RequestRec_send_fd(request_rec *r,
+                                             apr_os_file_t *fd,
+                                             apr_size_t length)
+{
+    apr_file_t *file = NULL;
+    apr_file_t *dup = NULL;
+    apr_size_t *nbytes;
+    apr_status_t rc = 0;
+
+    rc = apr_os_file_put(&file, fd, r->pool);
+    /* XXX: error checking */
+    rc = apr_file_dup(&dup, file, r->pool);
+    /* XXX: error checking */
+    rc = ap_send_fd(dup, r, 0, length, nbytes);
+
+    if (rc != APR_SUCCESS) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r, "ap_send_fd has failed");
+    }
+
+    return *nbytes;
+}





_____________________________________________________________________
Stas Bekman             JAm_pH      --   Just Another mod_perl Hacker
http://stason.org/      mod_perl Guide   http://perl.apache.org/guide
mailto:[EMAIL PROTECTED]  http://ticketmaster.com http://apacheweek.com
http://singlesheaven.com http://perl.apache.org http://perlmonth.com/


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to