stas        2003/03/02 19:39:07

  Modified:    xs/Apache/RequestIO Apache__RequestIO.h
               xs/Apache/SubRequest Apache__SubRequest.h
               src/modules/perl mod_perl.c modperl_filter.c
                        modperl_filter.h
               xs/tables/current/ModPerl FunctionTable.pm
               t/filter out_bbs_ctx.t out_str_ctx.t
               t/filter/TestFilter out_bbs_ctx.pm out_str_ctx.pm
               .        Changes
  Log:
  revamp the code handling output flushing and flush bucket
  sending. Namelly modperl_wbucket_flush and modperl_wbucket_pass now
  can be told to send a flush bucket by themselves, attaching it to the
  data bb they are already sending. This halfs the number of output
  filter invocations when the response handler flushes output via $| or
  rflush. adjust tests, which were counting the number of invocations.
  
  Revision  Changes    Path
  1.36      +3 -4      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.35
  retrieving revision 1.36
  diff -u -r1.35 -r1.36
  --- Apache__RequestIO.h       2 Mar 2003 13:32:26 -0000       1.35
  +++ Apache__RequestIO.h       3 Mar 2003 03:39:06 -0000       1.36
  @@ -23,8 +23,7 @@
   #define mpxs_output_flush(r, rcfg) \
       /* if ($|) */ \
       if (IoFLUSH(PL_defoutgv)) { \
  -        MP_FAILURE_CROAK(modperl_wbucket_flush(rcfg->wbucket)); \
  -        ap_rflush(r); \
  +        MP_FAILURE_CROAK(modperl_wbucket_flush(rcfg->wbucket, TRUE)); \
       }
   
   static MP_INLINE apr_size_t mpxs_ap_rvputs(pTHX_ I32 items,
  @@ -145,9 +144,9 @@
   
       rcfg = modperl_config_req_get(r);
   
  -    MP_FAILURE_CROAK(modperl_wbucket_flush(rcfg->wbucket));
  +    MP_FAILURE_CROAK(modperl_wbucket_flush(rcfg->wbucket, TRUE));
   
  -    return ap_rflush(r);
  +    return APR_SUCCESS;
   }
   
   static MP_INLINE long mpxs_ap_get_client_block(pTHX_ request_rec *r,
  
  
  
  1.3       +1 -1      modperl-2.0/xs/Apache/SubRequest/Apache__SubRequest.h
  
  Index: Apache__SubRequest.h
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/xs/Apache/SubRequest/Apache__SubRequest.h,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- Apache__SubRequest.h      23 Jan 2003 00:31:28 -0000      1.2
  +++ Apache__SubRequest.h      3 Mar 2003 03:39:06 -0000       1.3
  @@ -7,7 +7,7 @@
   
       if (r->main) {
           modperl_config_req_t *rcfg = modperl_config_req_get(r->main);
  -        MP_FAILURE_CROAK(modperl_wbucket_flush(rcfg->wbucket));
  +        MP_FAILURE_CROAK(modperl_wbucket_flush(rcfg->wbucket, FALSE));
       }
   
       return ap_run_sub_req(r);
  
  
  
  1.154     +1 -1      modperl-2.0/src/modules/perl/mod_perl.c
  
  Index: mod_perl.c
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/src/modules/perl/mod_perl.c,v
  retrieving revision 1.153
  retrieving revision 1.154
  diff -u -r1.153 -r1.154
  --- mod_perl.c        2 Mar 2003 13:26:25 -0000       1.153
  +++ mod_perl.c        3 Mar 2003 03:39:06 -0000       1.154
  @@ -742,7 +742,7 @@
       MP_dRCFG;
   
       /* flush output buffer */
  -    return modperl_wbucket_flush(rcfg->wbucket);
  +    return modperl_wbucket_flush(rcfg->wbucket, FALSE);
   }
   
   static int modperl_response_handler_run(request_rec *r, int finish)
  
  
  
  1.54      +81 -55    modperl-2.0/src/modules/perl/modperl_filter.c
  
  Index: modperl_filter.c
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_filter.c,v
  retrieving revision 1.53
  retrieving revision 1.54
  diff -u -r1.53 -r1.54
  --- modperl_filter.c  2 Mar 2003 10:30:56 -0000       1.53
  +++ modperl_filter.c  3 Mar 2003 03:39:06 -0000       1.54
  @@ -1,9 +1,54 @@
   #include "mod_perl.h"
   
  +/* helper funcs */
  +
  +#define MP_FILTER_POOL(f) f->r ? f->r->pool : f->c->pool
  +
  +MP_INLINE static apr_status_t send_input_eos(modperl_filter_t *filter)
  +{
  +    apr_bucket_alloc_t *ba = filter->f->c->bucket_alloc;
  +    apr_bucket *b = apr_bucket_eos_create(ba);
  +    APR_BRIGADE_INSERT_TAIL(filter->bb_out, b);
  +    ((modperl_filter_ctx_t *)filter->f->ctx)->sent_eos = 1;
  +    return APR_SUCCESS;
  +}
  +
  +MP_INLINE static apr_status_t send_input_flush(modperl_filter_t *filter)
  +{
  +    apr_bucket_alloc_t *ba = filter->f->c->bucket_alloc;
  +    apr_bucket *b = apr_bucket_flush_create(ba);
  +    APR_BRIGADE_INSERT_TAIL(filter->bb_out, b);
  +    return APR_SUCCESS;
  +}
  +
  +MP_INLINE static apr_status_t send_output_eos(ap_filter_t *f)
  +{
  +    apr_bucket_alloc_t *ba = f->c->bucket_alloc;
  +    apr_bucket_brigade *bb = apr_brigade_create(MP_FILTER_POOL(f),
  +                                                ba);
  +    apr_bucket *b = apr_bucket_eos_create(ba);
  +    APR_BRIGADE_INSERT_TAIL(bb, b);
  +    ((modperl_filter_ctx_t *)f->ctx)->sent_eos = 1;
  +    MP_TRACE_f(MP_FUNC, "sending EOS bucket in separate bb\n");
  +    return ap_pass_brigade(f, bb);
  +}
  +
  +MP_INLINE static apr_status_t send_output_flush(ap_filter_t *f)
  +{
  +    apr_bucket_alloc_t *ba = f->c->bucket_alloc;
  +    apr_bucket_brigade *bb = apr_brigade_create(MP_FILTER_POOL(f),
  +                                                ba);
  +    apr_bucket *b = apr_bucket_flush_create(ba);
  +    APR_BRIGADE_INSERT_TAIL(bb, b);
  +    MP_TRACE_f(MP_FUNC, "sending FLUSH bucket in separate bb\n");
  +    return ap_pass_brigade(f, bb);
  +}
  +
   /* simple buffer api */
   
   MP_INLINE apr_status_t modperl_wbucket_pass(modperl_wbucket_t *wb,
  -                                            const char *buf, apr_size_t len)
  +                                            const char *buf, apr_size_t len,
  +                                            int add_flush_bucket)
   {
       apr_bucket_alloc_t *ba = (*wb->filters)->c->bucket_alloc;
       apr_bucket_brigade *bb;
  @@ -56,20 +101,39 @@
       bucket = apr_bucket_transient_create(work_buf, len, ba);
       APR_BRIGADE_INSERT_TAIL(bb, bucket);
   
  +    if (add_flush_bucket) {
  +        /* append the flush bucket rather then calling ap_rflush, to
  +         * prevent a creation of yet another bb, which will cause an
  +         * extra call for each filter in the chain */
  +        apr_bucket *bucket = apr_bucket_flush_create(ba);
  +        APR_BRIGADE_INSERT_TAIL(bb, bucket);
  +    }
  +        
       MP_TRACE_f(MP_FUNC, "buffer length=%d\n", len);
   
       return ap_pass_brigade(*(wb->filters), bb);
   }
   
  -MP_INLINE apr_status_t modperl_wbucket_flush(modperl_wbucket_t *wb)
  +/* if add_flush_bucket is TRUE
  + *  and there is data to flush,
  + *       a flush bucket is added to the tail of bb with data
  + * otherwise
  + *       a flush bucket is sent in its own bb
  + */
  +MP_INLINE apr_status_t modperl_wbucket_flush(modperl_wbucket_t *wb,
  +                                             int add_flush_bucket)
   {
       apr_status_t rv = APR_SUCCESS;
   
       if (wb->outcnt) {
  -        rv = modperl_wbucket_pass(wb, wb->outbuf, wb->outcnt);
  +        rv = modperl_wbucket_pass(wb, wb->outbuf, wb->outcnt,
  +                                  add_flush_bucket);
           wb->outcnt = 0;
       }
  -
  +    else if (add_flush_bucket) {
  +        rv = send_output_flush(*(wb->filters));
  +    }
  +    
       return rv;
   }
   
  @@ -87,14 +151,14 @@
       
       if ((len + wb->outcnt) > sizeof(wb->outbuf)) {
           apr_status_t rv;
  -        if ((rv = modperl_wbucket_flush(wb)) != APR_SUCCESS) {
  +        if ((rv = modperl_wbucket_flush(wb, FALSE)) != APR_SUCCESS) {
               return rv;
           }
       }
   
       if (len >= sizeof(wb->outbuf)) {
           *wlen = len;
  -        return modperl_wbucket_pass(wb, buf, len);
  +        return modperl_wbucket_pass(wb, buf, len, FALSE);
       }
       else {
           memcpy(&wb->outbuf[wb->outcnt], buf, len);
  @@ -106,8 +170,6 @@
   
   /* generic filter routines */
   
  -#define MP_FILTER_POOL(f) f->r ? f->r->pool : f->c->pool
  -
   modperl_filter_t *modperl_filter_new(ap_filter_t *f,
                                        apr_bucket_brigade *bb,
                                        modperl_filter_mode_e mode,
  @@ -223,46 +285,6 @@
       return status;
   }
   
  -/* output filters */
  -
  -MP_INLINE static apr_status_t send_input_eos(modperl_filter_t *filter)
  -{
  -    apr_bucket_alloc_t *ba = filter->f->c->bucket_alloc;
  -    apr_bucket *b = apr_bucket_eos_create(ba);
  -    APR_BRIGADE_INSERT_TAIL(filter->bb_out, b);
  -    ((modperl_filter_ctx_t *)filter->f->ctx)->sent_eos = 1;
  -    return APR_SUCCESS;
  -    
  -}
  -
  -MP_INLINE static apr_status_t send_input_flush(modperl_filter_t *filter)
  -{
  -    apr_bucket_alloc_t *ba = filter->f->c->bucket_alloc;
  -    apr_bucket *b = apr_bucket_flush_create(ba);
  -    APR_BRIGADE_INSERT_TAIL(filter->bb_out, b);
  -    return APR_SUCCESS;
  -}
  -
  -MP_INLINE static apr_status_t send_output_eos(ap_filter_t *f)
  -{
  -    apr_bucket_alloc_t *ba = f->c->bucket_alloc;
  -    apr_bucket_brigade *bb = apr_brigade_create(MP_FILTER_POOL(f),
  -                                                ba);
  -    apr_bucket *b = apr_bucket_eos_create(ba);
  -    APR_BRIGADE_INSERT_TAIL(bb, b);
  -    ((modperl_filter_ctx_t *)f->ctx)->sent_eos = 1;
  -    return ap_pass_brigade(f->next, bb);
  -}
  -
  -MP_INLINE static apr_status_t send_output_flush(ap_filter_t *f)
  -{
  -    apr_bucket_alloc_t *ba = f->c->bucket_alloc;
  -    apr_bucket_brigade *bb = apr_brigade_create(MP_FILTER_POOL(f),
  -                                                ba);
  -    apr_bucket *b = apr_bucket_flush_create(ba);
  -    APR_BRIGADE_INSERT_TAIL(bb, b);
  -    return ap_pass_brigade(f->next, bb);
  -}
   
   /* unrolled APR_BRIGADE_FOREACH loop */
   
  @@ -501,26 +523,30 @@
   
   MP_INLINE apr_status_t modperl_output_filter_flush(modperl_filter_t *filter)
   {
  +    int add_flush_bucket = FALSE;
  +    
       if (((modperl_filter_ctx_t *)filter->f->ctx)->sent_eos) {
           /* no data should be sent after EOS has been sent */
           return filter->rc;
       }
   
  -    filter->rc = modperl_wbucket_flush(&filter->wbucket);
  +    if (filter->flush) {
  +        add_flush_bucket = TRUE;
  +        filter->flush = 0;
  +    }
  +
  +    filter->rc = modperl_wbucket_flush(&filter->wbucket, add_flush_bucket);
       if (filter->rc != APR_SUCCESS) {
           return filter->rc;
       }
   
  -    if (filter->eos || filter->flush) {
  -        MP_TRACE_f(MP_FUNC, "sending %s bucket\n",
  -                   filter->eos ? "EOS" : "FLUSH");
  -        filter->rc = filter->eos ?
  -            send_output_eos(filter->f) : send_output_flush(filter->f);
  +    if (filter->eos) {
  +        filter->rc = send_output_eos(filter->f->next);
           if (filter->bb_in) {
               apr_brigade_destroy(filter->bb_in);
               filter->bb_in = NULL;
           }
  -        filter->flush = filter->eos = 0;
  +        filter->eos = 0;
       }
   
       return filter->rc;
  
  
  
  1.21      +4 -2      modperl-2.0/src/modules/perl/modperl_filter.h
  
  Index: modperl_filter.h
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_filter.h,v
  retrieving revision 1.20
  retrieving revision 1.21
  diff -u -r1.20 -r1.21
  --- modperl_filter.h  25 Jan 2003 03:08:04 -0000      1.20
  +++ modperl_filter.h  3 Mar 2003 03:39:06 -0000       1.21
  @@ -16,9 +16,11 @@
   
   /* simple buffer api */
   MP_INLINE apr_status_t modperl_wbucket_pass(modperl_wbucket_t *b,
  -                                            const char *buf, apr_size_t len);
  +                                            const char *buf, apr_size_t len,
  +                                            int add_flush_bucket);
   
  -MP_INLINE apr_status_t modperl_wbucket_flush(modperl_wbucket_t *b);
  +MP_INLINE apr_status_t modperl_wbucket_flush(modperl_wbucket_t *b,
  +                                             int add_flush_bucket);
   
   MP_INLINE apr_status_t modperl_wbucket_write(pTHX_
                                                modperl_wbucket_t *b,
  
  
  
  1.107     +8 -0      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.106
  retrieving revision 1.107
  diff -u -r1.106 -r1.107
  --- FunctionTable.pm  2 Mar 2003 13:28:13 -0000       1.106
  +++ FunctionTable.pm  3 Mar 2003 03:39:06 -0000       1.107
  @@ -4577,6 +4577,10 @@
         {
           'type' => 'modperl_wbucket_t *',
           'name' => 'b'
  +      },
  +      {
  +        'type' => 'int',
  +        'name' => 'add_flush_bucket'
         }
       ]
     },
  @@ -4598,6 +4602,10 @@
         {
           'type' => 'apr_size_t',
           'name' => 'len'
  +      },
  +      {
  +        'type' => 'int',
  +        'name' => 'add_flush_bucket'
         }
       ]
     },
  
  
  
  1.2       +2 -1      modperl-2.0/t/filter/out_bbs_ctx.t
  
  Index: out_bbs_ctx.t
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/t/filter/out_bbs_ctx.t,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- out_bbs_ctx.t     15 Jan 2003 06:47:15 -0000      1.1
  +++ out_bbs_ctx.t     3 Mar 2003 03:39:06 -0000       1.2
  @@ -8,7 +8,8 @@
   plan tests => 1;
   
   my $blocks  = 33;
  -my $invoked = 100;
  +my $invoked = 34; # 33 bb made of data and 1 flush bucket (unbuffered print)
  +                  #  1 bb with EOS bucket
   my $sig = join "\n", "received $blocks complete blocks",
       "filter invoked $invoked times\n";
   my $data = "#" x $blocks . "x" x $blocks;
  
  
  
  1.2       +3 -1      modperl-2.0/t/filter/out_str_ctx.t
  
  Index: out_str_ctx.t
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/t/filter/out_str_ctx.t,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- out_str_ctx.t     15 Jan 2003 06:47:15 -0000      1.1
  +++ out_str_ctx.t     3 Mar 2003 03:39:06 -0000       1.2
  @@ -8,7 +8,9 @@
   plan tests => 1;
   
   my $blocks  = 33;
  -my $invoked = 100;
  +my $invoked = 67; # 33 bb made of data and 1 flush bucket (unbuffered print)
  +                  # 33 bb made of 1 flush bucket (rflush)
  +                  #  1 bb with EOS bucket
   my $sig = join "\n", "received $blocks complete blocks",
       "filter invoked $invoked times\n";
   my $data = "#" x $blocks . "x" x $blocks;
  
  
  
  1.3       +5 -1      modperl-2.0/t/filter/TestFilter/out_bbs_ctx.pm
  
  Index: out_bbs_ctx.pm
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/t/filter/TestFilter/out_bbs_ctx.pm,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- out_bbs_ctx.pm    2 Mar 2003 11:36:15 -0000       1.2
  +++ out_bbs_ctx.pm    3 Mar 2003 03:39:06 -0000       1.3
  @@ -78,7 +78,11 @@
   
       $r->content_type('text/plain');
   
  -    # make sure that 
  +    # just to make sure that print() won't flush, or we would get the
  +    # count wrong
  +    local $| = 0;
  +
  +    # make sure that:
       # - we send big enough data so it won't fit into one buffer
       # - use chunk size which doesn't nicely fit into a buffer size, so
       #   we have something to store in the context between filter calls
  
  
  
  1.2       +4 -0      modperl-2.0/t/filter/TestFilter/out_str_ctx.pm
  
  Index: out_str_ctx.pm
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/t/filter/TestFilter/out_str_ctx.pm,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- out_str_ctx.pm    15 Jan 2003 06:47:15 -0000      1.1
  +++ out_str_ctx.pm    3 Mar 2003 03:39:06 -0000       1.2
  @@ -65,6 +65,10 @@
   
       $r->content_type('text/plain');
   
  +    # just to make sure that print() flushes, or we would get the
  +    # count wrong
  +    local $| = 1;
  +
       # make sure that
       # - we send big enough data so it won't fit into one buffer
       # - use chunk size which doesn't nicely fit into a buffer size, so
  
  
  
  1.141     +8 -0      modperl-2.0/Changes
  
  Index: Changes
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/Changes,v
  retrieving revision 1.140
  retrieving revision 1.141
  diff -u -r1.140 -r1.141
  --- Changes   2 Mar 2003 22:47:19 -0000       1.140
  +++ Changes   3 Mar 2003 03:39:07 -0000       1.141
  @@ -10,6 +10,14 @@
   
   =item 1.99_09-dev
   
  +revamp the code handling output flushing and flush bucket
  +sending. Namelly modperl_wbucket_flush and modperl_wbucket_pass now
  +can be told to send a flush bucket by themselves, attaching it to the
  +data bb they are already sending. This halfs the number of output
  +filter invocations when the response handler flushes output via $| or
  +rflush. adjust tests, which were counting the number of invocations.
  +[Stas]
  +
   move ModPerl::RegistryCooker to use a hash as object (similar to mp1),
   to make it easier to subclass. [Nathan Byrd <[EMAIL PROTECTED]>]
   
  
  
  

Reply via email to