stas        2003/11/06 03:22:03

  Modified:    src/modules/perl modperl_io_apache.c modperl_io_apache.h
               xs/Apache/RequestIO Apache__RequestIO.h
               xs/maps  modperl_functions.map
               xs/tables/current/ModPerl FunctionTable.pm
               .        Changes
  Log:
  rewrite $r->read() and perlio read functions to use the same function,
  which completely satisfies the read request if possible, on the way
  getting rid of get_client_block and its supporting functions which
  have problems and will most likely will be removed from the httpd-API
  in the future. Directly manipulate bucket brigades instead.
  
  Revision  Changes    Path
  1.9       +81 -24    modperl-2.0/src/modules/perl/modperl_io_apache.c
  
  Index: modperl_io_apache.c
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_io_apache.c,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -u -r1.8 -r1.9
  --- modperl_io_apache.c       1 Nov 2003 09:25:02 -0000       1.8
  +++ modperl_io_apache.c       6 Nov 2003 11:22:02 -0000       1.9
  @@ -105,37 +105,17 @@
       PerlIOApache *st = PerlIOSelf(f, PerlIOApache);
       request_rec *r = st->r;
       long total = 0;
  -    int rc;
   
       if (!(PerlIOBase(f)->flags & PERLIO_F_CANREAD) ||
           PerlIOBase(f)->flags & (PERLIO_F_EOF|PERLIO_F_ERROR)) {
        return 0;
       }
   
  -    if (!r->read_length) {
  -        /* only do this once per-request */
  -        if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)) != OK) {
  -            ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
  -                         "mod_perl: ap_setup_client_block failed: %d", rc);
  -            return -1;
  -        }
  -    }
  -
  -    if (r->read_length || ap_should_client_block(r)) {
  -        total = ap_get_client_block(r, vbuf, count);
  +    total = modperl_request_read(aTHX_ r, (char*)vbuf, count);
   
  -        MP_TRACE_o(MP_FUNC, "wanted %db, read %db [%s]",
  -                   count, total,
  -                   IO_DUMP_FIRST_CHUNK(r->pool, vbuf, total));
  -
  -        if (total < 0) {
  -            /*
  -             * XXX: as stated in ap_get_client_block, the real
  -             * error gets lots, so we only know that there was one
  -             */
  -            ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
  -                         "mod_perl: $r->read failed to read");
  -        }
  +    if (total < 0) {
  +        PerlIOBase(f)->flags |= PERLIO_F_ERROR;
  +        /* modperl_request_read takes care of setting ERRSV */
       }
   
       return total;
  @@ -268,6 +248,83 @@
   
   #endif /* defined MP_IO_TIE_PERLIO */
   
  +/******  Other request IO functions  *******/
  +
  +
  +MP_INLINE SSize_t modperl_request_read(pTHX_ request_rec *r,
  +                                       char *buffer, Size_t len)
  +{
  +    long total = 0;
  +    int wanted = len;
  +    int seen_eos = 0;
  +    char *tmp = buffer;
  +    apr_bucket_brigade *bb;
  +
  +    if (len <= 0) {
  +        return 0;
  +    }
  +
  +    bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
  +    if (bb == NULL) {
  +        r->connection->keepalive = AP_CONN_CLOSE;
  +        return -1;
  +    }
  +
  +    do {
  +        apr_size_t read;
  +        int rc;
  +
  +        rc = ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES,
  +                            APR_BLOCK_READ, len);
  +        if (rc != APR_SUCCESS) { 
  +            /* if we fail here, we want to just return and stop trying
  +             * to read data from the client.
  +             */
  +            r->connection->keepalive = AP_CONN_CLOSE;
  +            apr_brigade_destroy(bb);
  +            sv_setpv(ERRSV,
  +                     (char *)apr_psprintf(r->pool, 
  +                                          "failed to get bucket brigade: %s",
  +                                          modperl_apr_strerror(rc)));
  +            return -1;
  +        }
  +
  +        /* If this fails, it means that a filter is written
  +         * incorrectly and that it needs to learn how to properly
  +         * handle APR_BLOCK_READ requests by returning data when
  +         * requested.
  +         */
  +        AP_DEBUG_ASSERT(!APR_BRIGADE_EMPTY(bb));
  +
  +        if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) {
  +            seen_eos = 1;
  +        }
  +
  +        read = len;
  +        rc = apr_brigade_flatten(bb, tmp, &read);
  +        if (rc != APR_SUCCESS) {
  +            apr_brigade_destroy(bb);
  +            sv_setpv(ERRSV,
  +                     (char *)apr_psprintf(r->pool, 
  +                                          "failed to read: %s",
  +                                          modperl_apr_strerror(rc)));
  +            return -1;
  +        }
  +        total += read;
  +        tmp   += read;
  +        len   -= read;
  +
  +        apr_brigade_cleanup(bb);
  +
  +    } while (len > 0 && !seen_eos);
  +
  +    apr_brigade_destroy(bb);
  +
  +    MP_TRACE_o(MP_FUNC, "wanted %db, read %db [%s]", wanted, total,
  +               IO_DUMP_FIRST_CHUNK(r->pool, buffer, total));
  +
  +    return total;
  +}
   
   
   
  
  
  
  1.2       +4 -1      modperl-2.0/src/modules/perl/modperl_io_apache.h
  
  Index: modperl_io_apache.h
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_io_apache.h,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -u -r1.1 -r1.2
  --- modperl_io_apache.h       20 Aug 2003 23:20:14 -0000      1.1
  +++ modperl_io_apache.h       6 Nov 2003 11:22:02 -0000       1.2
  @@ -25,5 +25,8 @@
   #define modperl_io_apache_init(pTHX)
   
   #endif /* #ifdef PERLIO_LAYERS */
  -    
  +
  +MP_INLINE SSize_t modperl_request_read(pTHX_ request_rec *r,
  +                                       char *buffer, Size_t len);
  +
   #endif /* MODPERL_IO_APACHE_H */
  
  
  
  1.39      +25 -35    modperl-2.0/xs/Apache/RequestIO/Apache__RequestIO.h
  
  Index: Apache__RequestIO.h
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/xs/Apache/RequestIO/Apache__RequestIO.h,v
  retrieving revision 1.38
  retrieving revision 1.39
  diff -u -u -r1.38 -r1.39
  --- Apache__RequestIO.h       20 Aug 2003 23:13:28 -0000      1.38
  +++ Apache__RequestIO.h       6 Nov 2003 11:22:02 -0000       1.39
  @@ -206,55 +206,45 @@
       (r->read_length || ap_should_client_block(r))
   
   /* alias */
  -#define mpxs_Apache__RequestRec_READ(r, buffer, bufsiz, offset) \
  -    mpxs_Apache__RequestRec_read(aTHX_ r, buffer, bufsiz, offset)
  +#define mpxs_Apache__RequestRec_READ(r, bufsv, len, offset) \
  +    mpxs_Apache__RequestRec_read(aTHX_ r, bufsv, len, offset)
   
   static long mpxs_Apache__RequestRec_read(pTHX_ request_rec *r,
  -                                         SV *buffer, int bufsiz,
  +                                         SV *bufsv, int len,
                                            int offset)
   {
  -    long total = 0;
  -    int rc;
  +    long total;
   
  -    if ((rc = mpxs_setup_client_block(r)) != APR_SUCCESS) {
  -        return 0;
  +    if (!SvOK(bufsv)) {
  +        sv_setpvn(bufsv, "", 0);
       }
   
  -    if (mpxs_should_client_block(r)) {
  -        long nrd;
  -        /* ap_should_client_block() will return 0 if r->read_length */
  -        mpxs_sv_grow(buffer, bufsiz+offset);
  -        while (bufsiz) {
  -            nrd = ap_get_client_block(r, SvPVX(buffer)+offset+total, bufsiz);
  -            if (nrd > 0) {
  -                total  += nrd;
  -                bufsiz -= nrd;
  -            }
  -            else if (nrd == 0) {
  -                break;
  -            }
  -            else {
  -                /*
  -                 * XXX: as stated in ap_get_client_block, the real
  -                 * error gets lots, so we only know that there was one
  -                 */
  -                ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
  -                         "mod_perl: $r->read failed to read");
  -                break;
  -            }
  -        }
  +    if (len <= 0) {
  +        return 0;
       }
   
  +    /* XXX: need to handle negative offset */
  +    /* XXX: need to pad with \0 if offset > size of the buffer */
  +
  +    mpxs_sv_grow(bufsv, len+offset);
  +    total = modperl_request_read(aTHX_ r, SvPVX(bufsv)+offset, len);
  +
       if (total > 0) {
  -        mpxs_sv_cur_set(buffer, offset+total);
  -        SvTAINTED_on(buffer);
  +        mpxs_sv_cur_set(bufsv, offset+total);
  +        SvTAINTED_on(bufsv);
       } 
  +    else if (total == 0) {
  +        sv_setpvn(bufsv, "", 0);
  +    }
       else {
  -        sv_setpvn(buffer, "", 0);
  +        /* need to return undef according to the read entry, but at
  +         * the moment we return IV, so need to change to return SV,
  +         * meanwhile just crock */
  +        if (SvTRUE(ERRSV)) {
  +            (void)modperl_errsv(aTHX_ HTTP_INTERNAL_SERVER_ERROR, r, NULL);
  +        }
       }
   
  -    MP_TRACE_o(MP_FUNC, "%d bytes [%s]", total, SvPVX(buffer));
  - 
       return total;
   }
   
  
  
  
  1.59      +2 -2      modperl-2.0/xs/maps/modperl_functions.map
  
  Index: modperl_functions.map
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/xs/maps/modperl_functions.map,v
  retrieving revision 1.58
  retrieving revision 1.59
  diff -u -u -r1.58 -r1.59
  --- modperl_functions.map     30 Aug 2003 02:33:26 -0000      1.58
  +++ modperl_functions.map     6 Nov 2003 11:22:02 -0000       1.59
  @@ -46,8 +46,8 @@
    SV *:DEFINE_CLOSE    | | request_rec *:r
    SV *:DEFINE_UNTIE    | | request_rec *:r, int:refcnt
    mpxs_Apache__RequestRec_sendfile | | r, filename=r->filename, offset=0, len=0
  - 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_read | | r, bufsv, len, offset=0
  + long:DEFINE_READ | | request_rec *:r, SV *:bufsv, int:len, int:offset=0
    mpxs_Apache__RequestRec_write | | r, buffer, bufsiz=-1, offset=0
    mpxs_Apache__RequestRec_print | | ...
    apr_ssize_t:DEFINE_WRITE | | \
  
  
  
  1.127     +27 -2     modperl-2.0/xs/tables/current/ModPerl/FunctionTable.pm
  
  Index: FunctionTable.pm
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/xs/tables/current/ModPerl/FunctionTable.pm,v
  retrieving revision 1.126
  retrieving revision 1.127
  diff -u -u -r1.126 -r1.127
  --- FunctionTable.pm  14 Oct 2003 17:32:40 -0000      1.126
  +++ FunctionTable.pm  6 Nov 2003 11:22:02 -0000       1.127
  @@ -5754,16 +5754,41 @@
         },
         {
           'type' => 'SV *',
  -        'name' => 'buffer'
  +        'name' => 'bufsv'
         },
         {
           'type' => 'int',
  -        'name' => 'bufsiz'
  +        'name' => 'len'
         },
         {
           'type' => 'int',
           'name' => 'offset'
         }
  +    ]
  +  },
  +  {
  +    'return_type' => 'SSize_t',
  +    'name' => 'modperl_request_read',
  +    'attr' => [
  +      'static'
  +    ],
  +    'args' => [
  +      {
  +        'type' => 'PerlInterpreter *',
  +        'name' => 'my_perl'
  +      },
  +      {
  +        'type' => 'request_rec *',
  +        'name' => 'r'
  +      },
  +      {
  +        'type' => 'char *',
  +        'name' => 'buffer'
  +      },
  +      {
  +        'type' => 'Size_t',
  +        'name' => 'len'
  +      },
       ]
     },
     {
  
  
  
  1.246     +6 -0      modperl-2.0/Changes
  
  Index: Changes
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/Changes,v
  retrieving revision 1.245
  retrieving revision 1.246
  diff -u -u -r1.245 -r1.246
  --- Changes   5 Nov 2003 19:36:15 -0000       1.245
  +++ Changes   6 Nov 2003 11:22:02 -0000       1.246
  @@ -12,6 +12,12 @@
   
   =item 1.99_11-dev - 
   
  +rewrite $r->read() and perlio read functions to use the same function,
  +which completely satisfies the read request if possible, on the way
  +getting rid of get_client_block and its supporting functions which
  +have problems and will most likely will be removed from the httpd-API
  +in the future. Directly manipulate bucket brigades instead. [Stas]
  +
   Since Apache2.pm pops /foo/Apache2 dirs to the top of @INC, it now
   also takes care of keeping lib and blib dirs before the system dirs,
   so that previously installed libraries won't get loaded instead of the
  
  
  

Reply via email to