pike.git / src / modules / Pipe / pipe.c

version» Context lines:

pike.git/src/modules/Pipe/pipe.c:1:   /*   || This file is part of Pike. For copyright information see COPYRIGHT.   || Pike is distributed under GPL, LGPL and MPL. See the file COPYING   || for more information.   || This module has been deprecated.   */    - #include "global.h" - #include "config.h" +    #include "module.h" -  + #include "config.h"   #include "threads.h" - #include "stralloc.h" +    #include "pike_macros.h" - #include "object.h" +    #include "constants.h"   #include "interpret.h" - #include "svalue.h" +    #include "pike_error.h"   #include "builtin_functions.h"   #include "fdlib.h"    - #include <sys/types.h> +    #include <sys/stat.h>      #ifdef HAVE_SYS_FILE_H   #include <sys/file.h>   #endif /* HAVE_SYS_FILE_H */      #include <errno.h>    - /* Some <sys/mman.h>'s (eg AIX 5L/ia64) contain a #define of MAP_VARIABLE -  * for use as the opposite of MAP_FIXED. -  * -  * "program.h" above has a conflicting definition of MAP_VARIABLE. -  */ - #undef MAP_VARIABLE -  +    #ifdef HAVE_SYS_MMAN_H   #include <sys/mman.h>   #else   #ifdef HAVE_LINUX_MMAN_H   #include <linux/mman.h>   #else   #ifdef HAVE_MMAP   /* sys/mman.h is _probably_ there anyway. */   #include <sys/mman.h>   #endif
pike.git/src/modules/Pipe/pipe.c:108:   #define MAX_BYTES_IN_BUFFER 65536      /*! @module Pipe    *!    *! Single socket output.    *!    *! Regular file output and (multiple, adding) socket output    *! with no mmap input.    *!    *! Multiple socket output without regular file output illegal. +  *! +  *! @note +  *! It is preferable to use the @[Shuffler] API, it is significantly +  *! more flexible.    */      static struct program *pipe_program, *output_program;      #ifdef THIS   #undef THIS   #endif   #define THIS ((struct pipe *)(Pike_fp->current_storage))   #define THISOBJ (Pike_fp->current_object)   
pike.git/src/modules/Pipe/pipe.c:196:   };      static ptrdiff_t offset_input_read_callback;   static ptrdiff_t offset_input_close_callback;   static ptrdiff_t offset_output_write_callback;   static ptrdiff_t offset_output_close_callback;   static ptrdiff_t mmapped, nobjects, nstrings, noutputs;   static ptrdiff_t ninputs, nbuffers, sbuffers;      void close_and_free_everything(struct object *o,struct pipe *); - static INLINE void output_finish(struct object *obj); - static INLINE void output_try_write_some(struct object *obj); + static inline void output_finish(struct object *obj); + static inline void output_try_write_some(struct object *obj);      /********** internal ********************************************************/      /* Push a callback to this object given the internal function number.    */   static void push_callback(ptrdiff_t no)   {    SET_SVAL(*Pike_sp, T_FUNCTION, -  DO_NOT_WARN(no + Pike_fp->context->identifier_level), +  no + Pike_fp->context->identifier_level,    object, THISOBJ);    add_ref(THISOBJ);    Pike_sp++;   }      /* Allocate a new struct input, link it last in the linked list */ - static INLINE struct input *new_input(void) + static inline struct input *new_input(void)   {    struct input *i;    ninputs++;    i=ALLOC_STRUCT(input);    i->type=I_NONE;    i->next=NULL;    if (THIS->lastinput)    THIS->lastinput->next=i;    else    THIS->firstinput=i;    THIS->lastinput=i;    return i;   }      /* Free an input struct and all that it stands for */ - static INLINE void free_input(struct input *i) + static inline void free_input(struct input *i)   {    debug_malloc_touch(i);       ninputs--;    switch (i->type)    {    case I_OBJ:    case I_BLOCKING_OBJ:    if (!i->u.obj) break;    if (i->u.obj->prog)
pike.git/src/modules/Pipe/pipe.c:270: Inside #if defined(HAVE_MMAP) && defined(HAVE_MUNMAP)
  #if defined(HAVE_MMAP) && defined(HAVE_MUNMAP)    munmap(i->u.mmap,i->len);    mmapped -= i->len;   #else    Pike_error("I_MMAP input when MMAP is diabled!");   #endif    break;       case I_NONE: break;    } -  free((char *)i); +  free(i);   }      /* do the done_callback, then close and free everything */ - static INLINE void pipe_done(void) + static inline void pipe_done(void)   {    if (TYPEOF(THIS->done_callback) != T_INT)    {    assign_svalue_no_free(sp++,&THIS->id);    apply_svalue(&(THIS->done_callback),1);    pop_stack();       if(!THISOBJ->prog) /* We will not free anything in this case. */    return;    /* Pike_error("Pipe done callback destructed pipe.\n"); */
pike.git/src/modules/Pipe/pipe.c:308:    }else{    if(THIS->living_outputs) return;    }    pipe_done();   }      /* Allocate a new buffer and put it at the end of the chain of buffers    * scheduled for output. Return 1 if we have more bytes in buffers    * than allowed afterwards.    */ - static INLINE int append_buffer(struct pike_string *s) + static inline int append_buffer(struct pike_string *s)    /* 1=buffer full */   {    struct buffer *b;       debug_malloc_touch(s);       if(THIS->fd!= -1)    {    ptrdiff_t len = s->len;    char *data = s->str;
pike.git/src/modules/Pipe/pipe.c:401:   /* Read some data from the blocking object.    *    */   static int read_some_data(void)   {    struct pipe *this = THIS;    struct input * i = this->firstinput;       if (!i || i->type != I_BLOCKING_OBJ) {    Pike_fatal("PIPE: read_some_data(): Bad input type!\n"); -  return -1; +  UNREACHABLE(return -1);    }    push_int(8192);    push_int(1); /* We don't care if we don't get all 8192 bytes. */    apply(i->u.obj, "read", 2);    if ((TYPEOF(sp[-1]) == T_STRING) && (sp[-1].u.string->len > 0)) {    append_buffer(sp[-1].u.string);    pop_stack();    THIS->sleeping = 1;    return(1); /* Success */    }       /* FIXME: Should we check the return value here? */    pop_stack();    /* EOF */    return(0); /* EOF */   }      /* Let's guess what this function does....    *    */ - static INLINE void input_finish(void) + static inline void input_finish(void)   {    struct input *i;       while(1)    {    /* Get the next input from the queue */    i=THIS->firstinput->next;    free_input(THIS->firstinput);    THIS->firstinput=i;   
pike.git/src/modules/Pipe/pipe.c:470:    }    THIS->sleeping=0;       low_start();    finished_p();   }      /* This function reads some data from the file cache..    * Called when we want some data to send.    */ - static INLINE struct pike_string* gimme_some_data(size_t pos) + static inline struct pike_string* gimme_some_data(size_t pos)   {    struct buffer *b;    ptrdiff_t len;    struct pipe *this = THIS;       /* We have a file cache, read from it */    if (this->fd!=-1)    {    char buffer[READ_BUFFER_SIZE];    ptrdiff_t sz = this->pos-pos;
pike.git/src/modules/Pipe/pipe.c:521:    /* Free the first buffer, and update THIS->pos */    b=this->firstbuffer;    this->pos+=b->s->len;    this->bytes_in_buffer-=b->s->len;    this->firstbuffer=b->next;    if (!b->next)    this->lastbuffer=NULL;    sbuffers-=b->s->len;    nbuffers--;    free_string(b->s); -  free((char *)b); +  free(b);       /* Wake up first input if it was sleeping and we    * have room for more in the buffer.    */    if (this->sleeping &&    this->firstinput &&    this->bytes_in_buffer<MAX_BYTES_IN_BUFFER)    {    if (this->firstinput->type == I_BLOCKING_OBJ) {    if (!read_some_data()) {
pike.git/src/modules/Pipe/pipe.c:568: Inside #if defined(HAVE_MMAP) && defined(HAVE_MUNMAP)
   this->pos += this->firstinput->len;    input_finish();    continue;    }    len = this->firstinput->len + this->pos - pos;    if (len > READ_BUFFER_SIZE) len=READ_BUFFER_SIZE;    tmp = begin_shared_string( len );    src = this->firstinput->u.mmap + pos - this->pos;   /* This thread_allow/deny is at the cost of one extra memory copy */    THREADS_ALLOW(); -  MEMCPY(tmp->str, src, len); +  memcpy(tmp->str, src, len);    THREADS_DISALLOW();    return end_shared_string(tmp);    }    else   #endif    if (this->firstinput->type!=I_OBJ)    {    /* FIXME: What about I_BLOCKING_OBJ? */    input_finish(); /* shouldn't be anything else ... maybe a finished object */    }
pike.git/src/modules/Pipe/pipe.c:600:    this->firstbuffer->s->len-    pos+this->pos);   }         /*    * close and free the contents of a struct output    * Note that the output struct is not freed or unlinked here,    * that is taken care of later.    */ - static INLINE void output_finish(struct object *obj) + static inline void output_finish(struct object *obj)   {    struct output *o, *oi;    struct object *obji;       debug_malloc_touch(obj);       o=(struct output *)(obj->storage);       if (o->obj)    {
pike.git/src/modules/Pipe/pipe.c:653:       finished_p(); /* Moved by per, one line down.. :) */       /* free_object(THISOBJ); */ /* What? /Hubbe */    }   }      /*    * Try to write some data to our precious output    */ - static INLINE void output_try_write_some(struct object *obj) + static inline void output_try_write_some(struct object *obj)   {    struct output *out;    struct pike_string *s;    size_t len;    INT_TYPE ret;       debug_malloc_touch(obj);       out=(struct output*)(obj->storage);   
pike.git/src/modules/Pipe/pipe.c:749: Inside #if defined(HAVE_MMAP) && defined(HAVE_MUNMAP)
      apply(obj, "query_fd", 0);    if(TYPEOF(sp[-1]) == T_INT) fd=sp[-1].u.integer;    pop_stack();       if (fd != -1 && fstat(fd,&s)==0)    {    off_t filep=fd_lseek(fd, 0L, SEEK_CUR); /* keep the file pointer */    size_t len = s.st_size - filep;    if(S_ISREG(s.st_mode) /* regular file */ +  && (filep >= 0) /* lseek() succeeded. */    && ((m=(char *)mmap(0, len, PROT_READ,    MAP_FILE|MAP_SHARED,fd,filep))+1))    {    mmapped += len;       i->type=I_MMAP;    i->len = len;    i->u.mmap=m;   #if defined(HAVE_MADVISE) && defined(MADV_SEQUENTIAL)    /* Mark the pages as sequential read only access... */    madvise(m, len, MADV_SEQUENTIAL);   #endif -  pop_n_elems(args); -  push_int(0); +     return;    }    }    }   #endif       i->u.obj=obj;    nobjects++;    i->type=I_OBJ;    add_ref(i->u.obj);
pike.git/src/modules/Pipe/pipe.c:808:    return;    }    }       if (i==THIS->firstinput)    {    push_callback(offset_input_read_callback);    push_int(0);    push_callback(offset_input_close_callback);    apply_low(i->u.obj,i->set_nonblocking_offset,3); -  pop_stack(); +     }    else    {    /* DOESN'T WORK!!! */    push_int(0);    push_int(0);    push_callback(offset_input_close_callback);    apply_low(i->u.obj,i->set_nonblocking_offset,3); -  pop_stack(); +     } -  -  pop_n_elems(args); -  push_int(0); +    }      /*! @decl void write(string bytes)    *!    *! Add an input string to this pipe.    */   static void pipe_write(INT32 args)   {    struct input *i;   
pike.git/src/modules/Pipe/pipe.c:915:    bytes = fd_write(THIS->fd, data, len);    } while((bytes < 0) && (errno == EINTR));    if (bytes < 0) break;    len -= bytes;    data += bytes;    }       sbuffers-=b->s->len;    nbuffers--;    free_string(b->s); -  free((char *)b); +  free(b);    }    THIS->lastbuffer=NULL;       /* keep the file pointer of the duped fd    THIS->pos=0; */    push_int(0);    apply(sp[-args-2].u.object,"set_id", 1); -  pop_n_elems(args+2); /* ... and from apply x 2 */ +     return;    }    pop_stack(); /* from apply */    }       THIS->living_outputs++;    /* add_ref(THISOBJ); */ /* Weird */       /* Allocate a new struct output */    obj=clone_object(output_program,0);
pike.git/src/modules/Pipe/pipe.c:975:    o->pos=THIS->pos;       push_object(obj); /* Ok, David, this is probably correct, but I dare you to explain why :) */    apply(o->obj,"set_id",1);    pop_stack();       push_int(0);    push_callback(offset_output_write_callback);    push_callback(offset_output_close_callback);    apply_low(o->obj,o->set_nonblocking_offset,3); -  pop_stack(); -  -  pop_n_elems(args-1); +    }      /*! @decl void set_done_callback(void|function(mixed:mixed) done_cb, @    *! void|mixed id)    *!    *! Set the callback function to be called when all the outputs    *! have been sent.    */   static void pipe_set_done_callback(INT32 args)   {
pike.git/src/modules/Pipe/pipe.c:1006:    Pike_error("Illegal argument to set_done_callback()\n");       if (args>1)    {    free_svalue(&THIS->id);    assign_svalue_no_free(&(THIS->id),sp-args+1);    }       free_svalue(&THIS->done_callback);    assign_svalue_no_free(&(THIS->done_callback),sp-args); -  pop_n_elems(args-1); +    }      /*! @decl void set_output_closed_callback(void|function(mixed, object:mixed) close_cb, @    *! void|mixed id)    *!    *! Set the callback function to be called when one of the outputs has    *! been closed from the other side.    */   static void pipe_set_output_closed_callback(INT32 args)   {
pike.git/src/modules/Pipe/pipe.c:1034:    TYPEOF(sp[-args]) != T_ARRAY))    Pike_error("Illegal argument to set_output_closed_callback()\n");       if (args>1)    {    free_svalue(&THIS->id);    assign_svalue_no_free(&(THIS->id),sp-args+1);    }    free_svalue(&THIS->output_closed_callback);    assign_svalue_no_free(&(THIS->output_closed_callback),sp-args); -  pop_n_elems(args-1); +    }      /*! @decl void finish()    *!    *! Terminate and reinitialize the pipe.    */ - static void pipe_finish(INT32 args) + static void pipe_finish(INT32 UNUSED(args))   { -  pop_n_elems(args); -  push_int(0); +     pipe_done();   }      /*! @decl void start()    *!    *! Start sending the input(s) to the output(s).    */ - static void pipe_start(INT32 args) /* force start */ + static void pipe_start(INT32 UNUSED(args)) /* force start */   {    low_start(); -  if(args) -  pop_n_elems(args-1); +    }      /*! @decl int bytes_sent()    *!    *! Return the number of bytes sent.    */   static void f_bytes_sent(INT32 args)   {    pop_n_elems(args);    push_int(THIS->sent);
pike.git/src/modules/Pipe/pipe.c:1083:    if (args<1 || TYPEOF(sp[-args]) != T_OBJECT)    Pike_error("Illegal argument to pipe->write_output_callback\n");       if(!sp[-args].u.object->prog) return;       if(sp[-args].u.object->prog != output_program)    Pike_error("Illegal argument to pipe->write_output_callback\n");       debug_malloc_touch(sp[-args].u.object);    output_try_write_some(sp[-args].u.object); -  pop_n_elems(args-1); +    }      static void pipe_close_output_callback(INT32 args)   {    struct output *o;    if (args<1 || TYPEOF(sp[-args]) != T_OBJECT)       if(!sp[-args].u.object->prog) return;       if(sp[-args].u.object->prog != output_program)
pike.git/src/modules/Pipe/pipe.c:1107:       if (TYPEOF(THIS->output_closed_callback) != T_INT)    {    assign_svalue_no_free(sp++,&THIS->id);    push_object(o->obj);    apply_svalue(&(THIS->output_closed_callback),2);    pop_stack();    }       output_finish(sp[-args].u.object); -  pop_n_elems(args-1); +    }      static void pipe_read_input_callback(INT32 args)   {    struct input *i;    struct pike_string *s;       if (args<2 || TYPEOF(sp[1-args]) != T_STRING)    Pike_error("Illegal argument to pipe->read_input_callback\n");   
pike.git/src/modules/Pipe/pipe.c:1137:    /* THIS DOES NOT WORK */    push_int(0);    push_int(0);    push_callback(offset_input_close_callback);    apply_low(i->u.obj,i->set_nonblocking_offset,3);    pop_stack();    THIS->sleeping=1;    }       low_start(); -  pop_n_elems(args-1); +    }    - static void pipe_close_input_callback(INT32 args) + static void pipe_close_input_callback(INT32 UNUSED(args))   {    struct input *i;    i=THIS->firstinput;       if(!i)    Pike_error("Input close callback without inputs!\n");       if(i->type != I_OBJ)    Pike_error("Premature close callback on pipe!.\n");   
pike.git/src/modules/Pipe/pipe.c:1165:    pop_stack();   #endif    apply(i->u.obj,"close",0);    pop_stack();    }    nobjects--;    free_object(i->u.obj);    i->type=I_NONE;       input_finish(); -  if(args) -  pop_n_elems(args-1); +    }      /*! @decl string version()    *!    *! Return the version of the module.    */   static void pipe_version(INT32 args)   {    pop_n_elems(args); -  push_text("PIPE ver 2.0"); +  push_static_text("PIPE ver 2.0");   }      /********** init/exit *******************************************************/      void close_and_free_everything(struct object *thisobj,struct pipe *p)   {    struct buffer *b;    struct input *i;    struct output *o;    struct object *obj;
pike.git/src/modules/Pipe/pipe.c:1207:    add_ref(thisobj); /* don't kill object during this */       while (p->firstbuffer)    {    b=p->firstbuffer;    p->firstbuffer=b->next;    sbuffers-=b->s->len;    nbuffers--;    free_string(b->s);    b->next=NULL; -  free((char *)b); /* Hubbe */ +  free(b); /* Hubbe */    }    p->lastbuffer=NULL;          while (p->firstinput)    {    i=p->firstinput;    p->firstinput=i->next;    free_input(i);    }
pike.git/src/modules/Pipe/pipe.c:1250:    free_svalue(& p->output_closed_callback);    free_svalue(& p->id);       SET_SVAL_TYPE(p->done_callback, T_INT);    SET_SVAL_TYPE(p->output_closed_callback, T_INT);    SET_SVAL_TYPE(p->id, T_INT);       /* p->done=0; */   }    - static void init_pipe_struct(struct object *DEBUGUSED(o)) + static void init_pipe_struct(struct object *DMALLOCUSED(o))   {    debug_malloc_touch(o);       THIS->firstbuffer=THIS->lastbuffer=NULL;    THIS->firstinput=THIS->lastinput=NULL;    THIS->firstoutput=NULL;    THIS->bytes_in_buffer=0;    THIS->pos=0;    THIS->sleeping=0;    THIS->done=0;
pike.git/src/modules/Pipe/pipe.c:1275:    THIS->id.u.integer=0;    THIS->living_outputs=0;    THIS->sent=0;   }      static void exit_pipe_struct(struct object *UNUSED(o))   {    close_and_free_everything(NULL,THIS);   }    - static void exit_output_struct(struct object *DEBUGUSED(obj)) + static void exit_output_struct(struct object *DMALLOCUSED(obj))   {    struct output *o;       debug_malloc_touch(obj);    o=(struct output *)(Pike_fp->current_storage);       if (o->obj)    {    if(o->obj->prog)    {
pike.git/src/modules/Pipe/pipe.c:1307:    if(!THISOBJ->prog)    Pike_error("Pipe done callback destructed pipe.\n");    }    free_object(o->obj);    noutputs--;    o->obj=0;    o->fd=-1;    }   }    - static void init_output_struct(struct object *DEBUGUSED(ob)) + static void init_output_struct(struct object *DMALLOCUSED(ob))   {    struct output *o;    debug_malloc_touch(ob);    o=(struct output *)(Pike_fp->current_storage);    o->obj=0;   }         /********** Pike init *******************************************************/      void port_setup_program(void);      void f__pipe_debug(INT32 args)   {    pop_n_elems(args); -  push_int(DO_NOT_WARN(noutputs)); -  push_int(DO_NOT_WARN(ninputs)); -  push_int(DO_NOT_WARN(nstrings)); -  push_int(DO_NOT_WARN(nobjects)); -  push_int(DO_NOT_WARN(mmapped)); -  push_int(DO_NOT_WARN(nbuffers)); -  push_int(DO_NOT_WARN(sbuffers)); +  push_int(noutputs); +  push_int(ninputs); +  push_int(nstrings); +  push_int(nobjects); +  push_int(mmapped); +  push_int(nbuffers); +  push_int(sbuffers);    f_aggregate(7);   }      /*! @endclass    */      /*! @endmodule    */      PIKE_MODULE_INIT