Pipes for NetRexx and Java Version 0.50 May 30, 1999

Copyright (c) E. J. Tomlinson <tomlins@cam.org>, 1997. All rights reserved This code is Beta and will contain bugs. Use it at your own risk.

$ Permission to use Pipes for NetRexx and Java for noncommercial applications is granted. Please contact me for commercial uses.

Pipes for Netrexx and Java is PROVIDED AS IS AND COMES WITH NO WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED. IN NO EVENT WILL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DAMAGES RESULTING FROM THE USE OF THIS SOFTWARE.

Parts of njPipes are Distributed under the GNU GENERAL PUBLIC LICENSE with NO WARANTEES of ANY kind. See CopyLeft.Txt for the licence and information on using, copying, modifing, and distributing this program.

Not withstanding the above disclaimers, I am very interested in suggestions, problems, bugs, and questions.

njPipes now can extract pipes from java code! You can now use njPipes without knowing NetRexx, though it still must be installed.

Select this link to download the latest version of Pipes for NetRexx and Java.

Select this link to download a previous version of Pipes for NetRexx and Java.

Select this to read the FAQ.

Thanks to Jeff Hennick and René Jansen for their important contributions.

Member of the NetRexx Ring Join the Ring
[Next Site] [Previous Site] [Back 2 Sites] [Next 5 Sites]
[List All] [Random Site]

Table of Contents

    1.  About this Program

    2.  Installation and Requirements

    3.  The Pipe Compiler

        a. Parameters
        b. Errors
        c. Debugging

    4.  Stages

        a. What can be piped
        b. Supplied stages
        c. Processing Ranges
$       d. Processing DelimitedStrings
$       e. Methods For Stages

    5.  Examples

        a. Using pipes with NetRexx and Java
        b. Using NetRexx stem variables in stages
        c. Using callpipe and addpipe
        d. Connectors - pipes as stages

    6.  Deadlocks

    7.  Known Bugs

    8.  Fixes and Changes

    9.  Futures

    10. A (semi)Formal Definition

    11. Commercial Use

    12. Trademarks Etc.

IBM Java Developer Website

The IBM Java Developer Website is dedicated to supporting the Java developer. It consists of FREE on-line Java courses, articles, jCentral search engine and frequently asked questions as well as other information to support and promote Java. Come Visit!

Here are some stats on the njPipes page

1. About this Program

    Pipes for NetRexx and Java implements a simple but very powerful piping
    methodology based on the one developed by John P. Hartmann of IBM.  A more
    complete and much faster implementation of pipes can be found in the various
    Pipeline products from IBM.

    Information about Pipes, including many interesting papers, can be found at:

    http://pucc.princeton.edu/~pipeline/

    CMS pipes are extremely useful.  Both NetRexx and Java look to have bright
    futures.  I missed pipes when working in NetRexx so I wrote these classes to
    make my life easier.

    The major difference from CMS is that njpipes are compiled into java .class
    files and then run.  This has implications that change how callpipe and
    addpipe can work - dynamic pipes are not practical.  This will remain a
    limitation unless some hardy soul wants to write a very fast pipe to
    java .class file compiler.  Currently pipes get converted to NetRexx,
    translated to java, and are compiled by javac.

    This implementation uses a thread for each stage.  The main pipe also uses a
    thread to monitor the stages for deadlock detection.  Stages are dispatched
    using Java's wait and notifyAll methods.  Data is not moved though the pipe.
    Its always referred via object pointers.  As the objects pass through the pipe
    only pointers are changed.  This implementation could be, and probably
    should be, improved upon.  Its not all bad though.  If you are lucky and
    have multiprocessing hardware, (and a Java that can use it) Pipes for
    NetRexx and Java takes advantage of it.  On a dual processor system, simple
    pipes are 30 to 50% faster using native vs green threads.

    To make it easier for an improved pipes implementation to get off the
    ground, I have included the source of a NetRexx Interface class in the pipes
    directory.  Its my hope that any new implementation will use this class as a
    base.  All the methods needed by stages should be in this class.  This way
    implementers are free to change how pipes work, what they look like when
    compiled, how they are compiled etc - but a simple recompile should produce
    working stages.  If you think there are missing methods please let me know.


1. Installation and Requirements

    To run Pipes for NetRexx and Java you need both Java and NetRexx runtime
    support installed.  To write your own pipes or stages you need compilers for
    both Java and NetRexx.  The OS2 JDK release for Java 1.1.7A and NetRexx 1.148
    where used to develop this code.  NetRexx 1.132 is required to use version
    025 and above as inner classes are used, any Java from 1.1.1 on should work.

    The installation has changed as of release 025.  The core classes for pipes
    and stages have been moved into njpipesC.jar.  This file may be added to
    your CLASSPATH.

    To install create an njpipes directory, cd into it and unzip the njpipes.zip.
    Then unzip the versioned njpipes file, unzip njpipesXXX.zip.  This will build
    the directory structure with with examples, docuementation, the njpipesC.jar,
    a pipe.bat and pipe.cmd.  If you unzipped on a drive other than C: or you
    placed njpipes in a subdirectory, edit the .bat (W95, NT) or the .cmd (OS/2)
    file to point to your njpipes.jar and you can start pipeing.

    Alternately you can add njpipesC.jar to your CLASSPATH.  If you anticipate
    modifing any of the built in stages, you will want to add a reference to
    the njpipes directory before the njpipesC.jar in the CLASSPATH.  This will
    make java see any class files in the njpipes subdirectories in before the
    classes in the jar.

    For NT the following variables or their equivalent need to be defined in the
    Control Panel, System, Environment page as user variables.  This assumes
    you are using the sun JDK with the performance pack applied.

    CLASSPATH = c:\jdk1.1.6\lib\NetRexxC.zip;c:\njpipes;c:\njpipes\njpipesC.jar;c:\NetRexx;.;c:\jdk1.1.6\lib\classes.zip
    JAVA_COMPILER = symcjit
    PATH = C:\jdk1.1.6\bin;.;

    To test your installation CD into the njpipes directory and type:

    java njp "(test) literal arg() ! dup 999 ! count words ! console"

    The first time you use the pipe command in a new directory it will
    create a default pipes.cnf file for you.  The double quotes are not
    really necessary in this case.  Using them will avoid grief as shells
    sometimes do very unexpected things, when least expected, to arguements.

    If you have added the njpipesC.jar to your CLASSPATH you can also use:

    java njp "(test) literal arg() ! dup 999 ! count words ! console"

    You should see a message that the pipe compiler is processing your pipe and
    soon after that messages from the NetRexx compiler as it processes the pipe.

    To run the pipe type:

    java test some words

    The pipe should then output:

    2000

|   If you have had njPipes working and it fails after a reinstall, it may be
|   due to source you have recompiled.  Its a good idea to delete any .class
|   files you have created in the pipes, stages or tests directories.  Also
|   check the readme.  There maybe requirements to recompile some of your
|   pipes.  The stageExit method, now used quite a bit, is a two edged sword.
|   On one hand it generates much faster pipes, on the other hand, it often
|   requires pipes to be recompiled.


    Back to Table of Contents


3. The Pipe Compiler

    You can use the compiler to compile simple pipes directly like the test
    pipe in section 2. You can also compile from files.  Pipes for NetRexx and
$   Java use the suffix .njp for pipes.  You can see examples of pipes in the
    examples directory.

    The compiler is invoked with the command:

    java njp <arguments>

    Where <arguments> are:

    <compopt>|<fileid> {<compopt>|<fileid>}   - compile the files listed
|   ( <name> { <compopt>} ) <pipe>            - compile the <pipe> name

    Where <compopt> is:

    -gen                        - keep the .nrx source of pipes following
    -nogen                      - delete the .nrx source.  This is the default
    -<option>                   - where <option> is a valid NetRexx option

    And <fileid> is:

    <name>.nrx                  - any NetRexx file
    <name>.njp                  - any pipe or NetRexx or Java souce using pipes
    <name>.grp                  - a file containing a list of <compopt>s and/or
                                  <fileid>s.  lines can be commented using '--'

    The <options> are:

    runaway <milliseconds>      - Interval to use for deadlock checking.  This
    or                            only detects true pipe deadlocks, not stages
    stall <milliseconds>          that are looping or hung.  (Should this be
                                  changed?)
    package <name>              - insert a NetRexx package statement
    import <name>               - insert a NetRexx import statement
    config <name>               - override the default config file name (see below)
    sep <char>                  - override the default stage separator '!'
    end <char>                  - override the default end of pipe separator '?'
    cont <char>                 - override the default line continuation character ','
    debug <flag>                - debugging options
    cache <Hashtable>           - a Hashtable to help clue in the JIT...


    When the pipe is contained in a file the options must be set there.

    When a pipe is read from a file, text on the same line following a '-- ',
    will be treated as a comment.

    When a file called 'pipes.cnf' exists in a directory the compiler will
    include it after the initial comment.  You can use this to put stages in
    packages or to setup standard imports so all your stages are found.  You can
    see examples of this the the stages, examples and tests directories.

    See section 10 for a definition of a <pipe>.

    Errors issued by the compiler.  Stages can issue additional messages.

    Error - name of pipe is missing
    Error - runaway time must be numeric
    Error - stall time must be numeric
    Error - debug level must be numeric, found 'lvl'
    Error - cache must be followed by a valid symbol, found 'work'
    Error - append or prefix stages cannot be labeled 'stg.word(1)'
    Error - missing stage/pipe after 'stg.word(1)'
    Error - missing range and/or stage/pipe after 'stg.word(1)'
    Error - specs has only one output stream, not requires two
    Error - pipe definition 'stg' must be terminated by 'pend'
    Error - pipe definition 'stg' must define a pipe
    Error - Label 'label' already used
    Error - Label 'label' must not be numeric
    Error - pipe 'stg' cannot have a label
    Error - connectors must be named
    Error - Label 'label' not defined
    Error - Use a nop stage between 'label' definition a second use
    Error - expected a colon after 'stg.word(1)'
    Error - pipe as stage definition 'stg' is missing a period
    Error - 'parms' incorrect.  Use: {({class} {size})} {A|D} {target}
    Error - need to use a nop stage between 's[c[i,j-1]]' 'ssep' 's[c[i,j]]'
    Error - problem reading group rc='r'
    Error - 'w' is unreconized
    Warning - could not delete 'fileid'
    Error - 'key' is only valid in a class
    Warning - Possible netrexx exit in 'arg()' at 'l'
    Error - pipe name and parms must be on same line as 'key'
    Error - Pipe name missing for 'key'
    Error - Body of 'wp' is empty
    Error - *: connectors not implemented.  Use *in: or *out:
    Error - Connector 'w1' should start with *in or *out
    Error - Missing colon at 'w1'
    Error - Connect 'w1' cannot contain a period
    Error - cannot connect 'in' to an input stream with 'key'
    Error - Pipe fragment 'sub' needs atleast one 'sep'
    Error - cannot connect 'out' to an output stream with 'key'
    Error - A object name cannot contain spaces, found: 'a'


    Debugging pipes

    To find out what is happening in pipeline you have three tools.  First,
    you can set a debug flag when you compile the pipe.  The bits you set
    in the flag control what it does:

      1  -  Show all pipes starting
      2  -  Show all pipes ending
      4  -  Show all stages starting
      8  -  Show all stages stopping
     16  -  Show all Commit requests
     32  -  Show all Commit completions
     64  -  Show StageErrors raised via stage's Error(int,String) method.  The
            stage class uses Error for all its StageError signals.
    128  -  Show the arguement that each stage is recieving.  Handy since
            shells have a habbit of doing unexpected thing to arguements.
            (try: java findtext exit *.nrx vs java findtext "exit *.nrx")

         -  If there is a need I can easily add more events - just ask.

    To create a flag to see all stages starting and stopping you would
    add 8+4 and use:

    java njp (apipe debug 12) ...

    The second option is to use the invoke the dump() method in a stage.
    This dumps the status of the pipe using the same format you see when
$   a pipe deadlocks.  Using dump() does not normally cause a pipe to
$   terminate.  Once in a while dump() will generate an exception.  This
$   happens since dump() does not use protect or syncronize so it does not
$   stall.


    When all else fails, you can recompile all the stages used by the pipe
    with trace results enabled.  As of NetRexx 1.140 trace displays the
    context of the trace output.  With this, it is possible to see exactly
    what the stages are doing.  If this does not help send me the pipe and
    I will see if I cannot figure it out - you may have found a njPipes
    bug.

    One nasty error I have encountered is coding an exit instead of an
    exit(rc).  An exit alone will end the pipe very abruptly - the compiler
    should now warn about this...


    Back to Table of Contents


4. Stages

    Pipes for NetRexx and Java moves objects through pipes using stages.  This
    implies that almost anything can be piped.  There are a few things to
    remember.  Many of the supplied stages expect Rexx Objects and will fail
    when they do not get them.  I wonder if anyone will come up with a use for
    piping pipes?

    Standard Stages currently available can be found in the stages directory.
    Not all options available on the equivalent CMS stages have been implemented
    and error checking is not always complete.

    Here are a list of stages you can use now:

  c abbrev
  c append               -- the appended stage can be started at any time
  c array
  c arraya
  c arrayr
  c arrayw
  c between
  c buffer
  c change    (rexx)
  c casei
  c chop
    command   (rexx)     -- examples work in OS2, NT & Solaris not in W95
    compare   (rexx)
  c console   (rexx)
  c copy
  c count     (both)     -- lines (objects), words, chars, max, & min (rexx)
    dam
    deblock
  c deal
    dict
    dicta
    dictr
    dictw
    disk
    diska
    diskr
    diskslow
    diskw
  c drop
  c dup
    elastic              -- Implemented with two threads...
  c fanin
    faninany
  c fanout
  c fblock
    file
    filea
    filer
    fileslow
    filew
  c frlabel
    frtarget
    gate
    getfiles
    getovers
    getstems
  c find      (rexx)
    hash
    hasha
    hashr
    hashw
  c hole
  c insert
  c inside
  c join      (rexx)
  c joincont
  c juxtapose
  c literal
  c locate    (rexx)
  c lookup    (rexx)
    not                  -- A stage modifier.  Useage: not <stage>
                            Swaps output streams zero and one of <stage>
                            Usually used with a selection stage like find or locate
    noEofBack
    nop                  -- see section 10
  c notinside
  c nfind
    over                 -- read all subscripts of a stem (like loop over)
  c outside
  c pad
  c pick
    prefix
  c reverse   (rexx)
    rexx
  c serialize
    specs                -- massage the data.  Selections via start.length
                         -- start-end, start-* and -from_end;-from_end.  These
                         -- selections can also be prefixed with 'word'.  The
                         -- conversion functions upper, lower, b2x, d2x, x2b and x2d
                         -- are implemented as are format options left, right and
                         -- center.  The stop, select, read, readstop, pad and
                         -- write functions work too.
                         -- The number, TODclock and many other conversion
                         -- functions are not implemented.
  c split     (rexx)
    stem
    stema
    stemr
    stemw
    String
  c strfind
  c strnfind
  c strfrlabel
  c strliteral
  c strfrlabel
    sort                 -- sort objects: sort {({<Class>} {<size>} {A|D} {IRange}
                            Where <Class> is a sortClass.  The default is: Rexx
                            and <size> is the maximin number of objects, 10000 is the default.
    sortClass            -- interface to allow other object type to be sorted
    sortRexx             -- the default sortClass implementation
    sqlselect            -- query SQL via JDBC (a submitted stage)
  c take
    tcpclient
    tcpdata
    tcplisten
  c timestamp
  c tokenize
  c tolabel
    totarget
    timer                -- time pipes
| c unique
    var                  -- this can only read vars
    vector
    vectora
    vectorr
    vectorw
  c xlate                -- translate data (a submitted stage)
  c zone

    Stages prefixed by 'c' should work very much like CMS stages.
$    (Rexx) means the stage requires rexx objects as input

    The methods you can use in stages are documented here.


$   

Ranges

The interface to rexx ranges is in the pipes\IRange and pipes\utils. From an Email from Jeff Hennick here is how IRange works: $ Iranges in njpipes are a superset of those in CMS pipes. CMS supports $ only simple character ranges in parenthisis, njpipes alows any combinations, $ including SUBSTRING ... OF ..., etc., and -n;-m as a single range. A Rexx string is scanned for a inputrange word or a parenthesized group of inputranges and modifiers. An IRange object is created for each range, and returned as an array. The 0-element contains information about the entire group: number of elements, and the rest of the input string after the inputrange(s) have been removed. Usually, the input string is part of a stage argument. Input ranges can be specified by character, word, or fields; as singles, or consecutive positions. They may be referenced to either the left or right end of the string. They may be subranges of a range. The character to define words and fields may be specified. The IRanges are then used to select a sub-string of any Rexx string. Additional information is then also available: the sub-string's position in the string, the contents of the string before and after the sub-string, etc. Usually, the string is the input record read by the stage. Examples: $ instring = 'Word 4-7' -- usually, this string is part of the stage argument -- or -- $ instring = '(20.4 word 4-7 fieldseparator - f3 words-4.2 -40.8) some more data' ir = IRange[] ir = GetIRanges(instring) -- parses the string into range objects -- these can be used now $ numberOfRanges = ir[0].Number() -- "5" for the above instring $ extra = ir[0].Residue() -- "some more data" for the above $ -- usually, the dataString would be the input string $ -- from peekto(), inside the main loop of a stage $ dataString = '-NetRexx for Java -Create Java code faster -For easier internet programming' -- a single sub-string can be picked: $ sub_string = ir[2].selIRange(dataString) -- "-Create Java code faster" -- word 4-7 $ -- and a series of additional information is $ -- also available. For example: starting = ir[2].StartCol() -- "19" len = ir[2].Length() -- "24" last = ir[2].EndCol() -- "42" before = ir[2].Prefix() -- "-NetRexx for Java " after = ir[2].Residue() -- " -For easier internet programming" $

Delimited Strings in Stage Arguments

$ $ To aid in identifying and using full CMS-type delimited strings a type and methods $ are provided in the pipes package. $ $ Where a delimited string may be at the beginning of a string, use: $ $ arg_string = '/The NetRexx Language/ by M. F. Cowlishaw' -- Maybe $ $ ds = DString(arg_string) -- ds is a DString object $ delimstring = ds.String() -- "The NetRexx Language" $ rest = ds.Residue() -- " by M. F. Cowlishaw" $ $ If no delimited string is found at the beginning of the input string, the String() $ method returns "", and the full string is returned by Residue(). If the Residue is $ not needed, use: $ $ delimstring = DString(arg_string).String Back to Table of Contents

5. Examples

    Writing your own pipes or stage is simple.  Take a look at the source of the
    supplied stages in the stages directory.  Here are some more examples.  The
    first shows how to use a pipe in a NetRexx program:

    -----------------------------------------------------------------------
    -- examples\testpipe.njp
    -- to compile use: pipe testpipe.njp
    --             or: java njp testpipe.njp
    -- to execute use: java testpipe some text

    import pipes.
    import stages.

    class testpipe extends Object

    method testpipe(avar=Rexx)

       F = Rexx 'abase'
       T = Rexx 1

       F[0]=5
       F[1]=222
       F[2]=3333
       F[3]=1111
       F[4]=55
       F[5]=444

       pipe (apipe stall 1000 )
            stem F ! sort ! prefix literal {avar} ! console ! stem T

       loop i=1 to T[0]
          say 'T['i']='T[i]
       end

    method main(a=String[]) static

       testpipe(Rexx(a))

    -----------------------------------------------------------------------

    A couple things can be inferred from this example.  First its simple to
    pass rexx variables to pipes using STEM.  Also look at the  phrase {avar}.
    It passes the Rexx variable's value to the stage at runtime.  In CMS the pipe
    would be quoted and you would unquote sections to get a similiar effect.
    Another thing to note is that the pipe extraction program is fairly smart.
    It detects when pipes takes several lines.  As long as there are stages,
    or the current line ends with a stagesep or stageend character, or the next
    line starts with a stagesep or stageend character.  It gets added to the
    pipe.

$   The arg(), arg(rexx) or arg(null) methods get the arguments passed to a
    stage or pipe.  To get the complete rexx string of an arguement use arg().
    To get the nth word of a rexx arguement use arg(n).  When using pipes in
    netrexx or java code you can use arg('name') to get the named arguement.
    If the class of the arguement is not rexx use arg(null) to get the object.
    In .njp files you can use {avar} phrase actually just shorthand for
    arg('avar').

    The following example shows what has to be done in a
    stage to access the rexx variables passed by VAR, STEM and OVER.  The real
    over stage is a bit more complete.

    -----------------------------------------------------------------------
    -- over.nrx

    package stages

    import pipes.

    class over extends stage final

    method run() public

    a = getRexx(arg())

    loop i over a
       output(a[i])
    catch StageError
       rc = rc()
    end

    exit(rc*(rc<>12))

    -----------------------------------------------------------------------

    The getRexx method is passed the name of a string by the pipe.  In the
    previous example it would be passed A and would return an Object pointer
    to A in testpipe.

    If you wish to replace a stream this can be done using
    connectors.  For example look at the following fragment:

    -----------------------------------------------------------------------
    -- examples\calltest.njp

    pipe (callt1) literal test ! calltest {} ! console

    import pipes.

    class calltest extends stage final

    method run() public

       do
          a = arg()

          callpipe (cp1) gen {a} ! *out0:

          loop forever
             line = peekto()
             output(line)
             readto()
          end

       catch StageError
          rc = rc()
       end

    exit(rc*(rc<>12))
    -----------------------------------------------------------------------

$   Running the callt1 pipe with an argument of 10 would pass the 10 to
    calltest via {} and arg().  Then cp1's gen stage would be passed 'a'
    which is set to 10.  Since gen generate numbers in sequence, the console
    stage of callt1 would get the numbers from 1 to 10.  Now cp1 ends and
    calltest's output stream is restored and calltest unblocks and reads the
    the literal's data 'test' and passes it to console.

    The use of {} only works when compiling from .njp files.  It will not
    work from the command line.

    The njpipes compiler reconizes connectors as labels
    with the following forms:

    *in:
    *inN:
    *out:
    *outN

    When N is a whole number, the connector connects input or output
    stream N of the stage with the connector.

    When the label *in or *out, the connector connects the stages's current
    input or output stream with the connector.  This is used instead of *: due
    to the way the compiler/preprocessor works.

    If you do not want the stage to wait for the called pipe to complete you
    can use addpipe.  Here is an example.

    -----------------------------------------------------------------------
    -- similar to examples\addtest.njp

    a  = 100
    b  = 'some text for literal'

    addpipe (linktest) literal {b} ! dup {a} ! *in0:

    loop forever
       line = Rexx readto()
    catch StageError
    end

    -----------------------------------------------------------------------

    readto() will get 'some text for literal' one hundred times.

|   A quick aside.  When writing stages remember that njPipes moves objects
|   through pipes.  Use 'value = peekto()' instead of 'value = rexx peekto()'
|   when ever possible.  Some of the supplied stages pass objects with
|   classes other than rexx and forcing rexx will cause classCastExceptions.
|   If a stage needs a rexx object try using the rexx stage modifier to attempt
|   to convert the object.  Feel free to expand this stage, but please
|   send me the updated version.

 DISABLED  The following example shows how to use a pipe as a stage:
 DISABLED
 DISABLED  -----------------------------------------------------------------------
 DISABLED
 DISABLED  (linkpipe) gen arg() ! *out:
 DISABLED
 DISABLED  (linktest)
 DISABLED     genpipe= linkpipe(100) ?
 DISABLED     .genpipe.out !
 DISABLED     locate /0/ !
 DISABLED     console
 DISABLED
 DISABLED  -----------------------------------------------------------------------
 DISABLED
 DISABLED  The syntax of the above pipe is a bit different.  It works like this.  Pipes
 DISABLED  are special cases of stages.  A pipe that is intended to be used in place of
 DISABLED  a stage must define connectors.  When a pipe is used as a stage the
 DISABLED  convention is:  The instance of the pipe must be defined (genpipe=), when
 DISABLED  the instance is used the syntax is: {connector}.pipeinstance.{connector}
 DISABLED
 DISABLED  This is done since, in this implementation, pipes must be precompiled.

|   Serious stage writers will probably want to take a good look at the methods
|   defined in pipes\utils.nrx.  There you will find various methods for parsing
|   ranges.  You will also find the stub for the stageExit compiler exit.  It can
|   be used to produce 'on the fly' code at compile time.  You can also use it
|   to change the topology of the unprocessed part of the pipe.  The major use
|   is to allow implementations of stages like prefix, append or zone.  Its also
|   used to produce better performing stages, for an example see specs.

|   The compiler also queries the rexxArg() and stageArg() methods.  If your
$|  stage expects objects of class Rexx as arguments rexxArg() should return
|   the number of variables expected.  If your stage expects a stage for an
$|  argument, stageArg() should return the word position of the stage.

    To get a good idea of what can be done with pipes look at the tasktest pipe
    in the examples directory.  It, using code from Melinda Varins 'Cramming
    for the Journeyman Plumber Exam' paper,  implements the shell of a
    multitasking server - using about eight stages.  The file examples\tcptask.njp
    contains an example of this technique being used.

    Back to Table of Contents


6. Deadlocks

    Pipes for NetRexx and Java detects deadlocks and outputs information to allow
    you to fix the problem.  Consider the following session:

    -----------------------------------------------------------------------

    [D:\njpipes]java njp (deadlock) literal test ! a: fanin ! console ! a:
    Pipes for NetRexx and Java version 0.33
    Copyright (c) E. J. Tomlinson , 1998.  All rights reserved.
    Building pipe deadlock
    NetRexx portable processor, version 1.140
    Copyright (c) IBM Corporation, 1998.  All rights reserved.
    Program deadlock.nrx
    Compilation of 'deadlock.nrx' successful

    [D:\njpipes\examples]java -nojit deadlock
    test
    Deadlocked in deadlock

    Dumping deadlock Monitored by deadlock

     Flag units digit:  1=wait out, 2=wait in, 4=wait any, 8=wait commit
                     : 10=pending autocommit, 20=pending sever

     literal_1
     Running rc=0 commit=-1 Flag=201
     -> out 0 fanin_2 1 test

     fanin_2
     Running rc=0 commit=-1 Flag=101
     -> in  0 literal_1 1 test
        in  1 console_3 0 test
     -> out 0 console_3 1 test

     console_3
     Running rc=0 commit=-1 Flag=101
     -> in  0 fanin_2 1 test
     -> out 0 fanin_2 0 test

    Dumped Pipe deadlock Flag 40F rc=16

    RC=16

    -----------------------------------------------------------------------

    We can see that there are three stages Running.  None have any return
    codes set.  The Flags tell us that all the stages are waiting for an
    output to complete.  The '->' show which stream is selected.  From this
    we can see console_3 is trying to output to fanin_2.  Unfortunately fanin_2
    is waiting for output on stream 0 to complete, it cannot read the data
    waiting on in stream 1.  Hence the stall.

    When a stream has data being output, there is a boolean flag following the
    name of the stage the stream is connected to.  This tracks the peek state of
    the object.  For an output stream, true means the following stage has peeked
    at the value.  With input streams, the current stage has seen the value when
    its true.

    When a stage is multithreaded, like elastic, you can get flags of 3 or 5.
    This means that threads are waiting on output and read, or output and any.
    When using multithreaded stages, only one thread should use output unless it
    is serialized using protected or syncronized blocks.

    When a stage has a pending sever or autocommit flag bits are set too.

    Back to Table of Contents


7. Known Bugs

    I expect problems with add/callpipe.  The cases tested in addtest1 thru
    addtest8, calltest1 thru calltest3, siptest, tcpexample, tcptask and
    spawntest, all work ok but other types of connections may or may not work
    correctly.  Good news is that the last few tests (tcptask, spawntest) did
    not break anything.  The testcases also work on a dual processor system.

    The command stage can fail when more that one instance is used at the same
    time.  This is due to a Java OS/2 problem with unnamed pipes.  Also passing
    an invalid command can terminate your program...  There are also problems
    with command under W95.  Command should be rewritten to use a thread for
    each output stream and it should handle cases where syserr does not exist.

    While this is not strictly speaking a bug, it can cause unexpected results.
    Often using a JIT can slow down pipes.  This is because java, and hense
    the JIT, likes to garbage collect objects quickly.  Pipes load lots of
    classes, the JIT compiles them, the pipe ends and java garbage collects
    the objects and the JIT loses its code.  In release 027 I added code to
    help callpipe and addpipe used in stages.  In release 029 the cache option
    was introduced so you can pass a Hashtable from your main routine to pipes
    to be used for the object cache.  This way calling a pipe many times will
    not end up causing the JIT to work too hard.

|   Sun's JIT for NT and W9x will sometimes raise a NullPointerException when
|   none should occur.  The fix is to use the -nojit option when running the
|   pipe or to upgrade to the, prerelease, JIT available at Sun's javasoft
|   site.  In general, when something wierd happens with java, try again with
|   the JIT off.

    Please Report bugs to: tomlins@cam.org

    Back to Table of Contents


8. Fixes and Changes

   0.50  - Released May 30, 1999
         - Fixed a stall occuring when interruped threads, with the interrupt
           caught by ThreadPool, were reused.
         - Fixed a thread safety problem in ELASTIC
         - Improved the timeout options in TCPDATA and TCPCLIENT, they also
           byte[] instead of strings.  This was done since converting to and
           from strings sometimes scrambles binary data (more research on
           encodings...)
         - Changed DELBLOCK it now handles byte[] to help keep tcpdata and
           tcpclient efficent.  The EOF option was broken, its fixed now.
         - Changed DISKR, DISKW and DISKA to handle byte[] when using streams.
         - Added INSERT which handles byte[].  This should be used instead of
           SPECS to add LF or CR .
         - Changes SERIALIZE to use byte[].
   0.49  - Released May 21, 1999
         - compiled with 1.2.1 and netrexx 1.148
         - Added preliminary support added to .njp compiler for files containing
           java source!  See the (some what messy) java samples in vectort1.njp,
           overtest.njp and addtest4.njp
         - Added code to generate a dummy .nrx file containing the public class
           in a .java file.  This allows NetRexx to compile class that depend on
           the java source.
         - Modified sort to accept arguements in the same order as CMS
         - Fixed rc logic in drop stage
         - Fixed shortcut code for {n} where n is numeric.
   0.48  - Released May 16, 1999
         - Fixed a (nasty) bug involving reusing pipe objects.
         - Added the reuse() method to the stage class.  To use it override
           it in your stage.  It was added so there was a foolproof way to
           reset a stage when its pipe object is reused.  (doSetup is intended
           for use with dynamic arguements in call or added pipes)
         - Added the cont option and defaulted it to comma.
         - fixed return code logic in some stages and in selectInput/Output
         - Added the Emsg methods
         - Added arguement debug option (128)
         - There are no more final methods
         - Much improved error reporting from stages via new Emsg method
   0.47  - Released Jan 3, 1999
         - recompiled with 1.1.7A and netrexx 1.148
         - UNIQUE repaired?
         - Added stages to acess java objects easily
           VECTOR, VECTORR, VECTORW, VECTORA for java.util.vector
           ARRAY, ARRAYR, ARRAYW, ARRAYA for Object[]
           HASH, HASHR, HASHW, HASHA for java.util.Hashtable
           DICT, DICTR, DICTW, DICTA for java.util.Dictionary
           The hash stages mostly map directly to DICT stages.  The exception
           is HASHW which uses the clear() method of Hashtable.
         - Modified LITERAL to be able to put any object into a pipe
         - Modified pipe package to store arguements in a hashtable instead of
           a rexx stem - arguements can now be of any class.  Use the arg(null)
           method to get an object arguement.
   0.46a - Released Oct 14, 1998
         - recompiled with 1.1.7
         - TCPLISTEN now supports an input stream to be used to pace accepts
   0.46  - Released Sept 20, 1998
         - COMMAND, CHANGE, FILE, LOCATE, DROP, LOOKUP, TCPCLIENT, TCPLISTEN
           SQLSELECT, CONSOLE, TCPDATA, NOEOFBACK improved.
         - Jeff improved the testing process with the addition of the COMPARE
           stage, he also upgraded many of the tests.
         - Added the buildtests pipe, it builds a test script to be run with:
           test > output < console.data
         - Unexpected exceptions should no longer hang pipes
   0.45  - Released Sept 9, 1998
         * Recompile all your stages.  To fix a commit problem I had to
           change the _stage interface class...
         - tcpclient restart problems with oneresp active fixed.
         - commit now returns the current return code of the pipe.
         - fixed minor errors in tcpclient and diska.
   0.44  - Released Sept 8, 1998
         * a recompile of pipes using STEM is required
         - smart DISK, FILE and STEM stages now exist.
         - Made to and from synonoms for in and out in REXX and STRING stages.
         - Added stream option to DISKR and DISKW to read raw streams.
         - Added DISKSLOW and SERIALIZE stages.
         - Now DISK, DISKR, DISKW, DISKA and DISKSLOW have FILE synonyms.
         - Deadlock detection improvements.
         - TCPDATA & TCPCLIENT optimized once again.
         - selectAnyInput could deadlock - fixed.
         - interrupting a pipe now kills it - use this with care (ie. kill -9)
         - Pseudo methods njpRC() and njpObject() are reconized by the pipes
           compiler and return the pipe's RC or object respectivily.
   0.43  - Released August 30, 1998
         - Fixed deadlock dection to see commit deadlocks.
         - Added rest of code to handle improved StageError logic.
         - Added stage templates (template*.nrx) in the njpipes directory.
         - Added a debug flag (64) to trace all StageError rasied by the
           stage class.
   0.42  - Not released
         * A recompile of pipes using TCPCLIENT, TCPDATA is required.
         * A recompile of pipes using REXX, STRING, ZONE, CASEI is recommended.
         - Updated the comments in _stage to reflect the possible StageError
           and return codes that can be issued.
         - Added the DEBLOCK stage and reworked TCPDATA, TCPCLIENT & GATE.
         - Improved eofReport processing and added a new option 'either' that
           will trigger a StageError when any stream, input or output, severs.
         - Fixed variable subsitution so multiple variables passed to a stage
           will work.
         - Added the ability to pass thru arguements to callpipe and addpipe.
         - Fixed a problem with some StageExits requiring stage_reset methods.
         - Added a function to utils to help assign smarter name to classes
           generated by StageExits.
         - Added counter method to stage.  use to count external waits so
           deadlock/stall detection is not fooled.
   0.41  - Released August 23, 1998
         * removed OBJ2REXX, OBJ2STRING stages, use REXX and STRING stage
           modifiers.
         * pipes using TCPDATA, TCPCLIENT & LOOKUP should be recompiled
         - exhanced REXX stage modifier via an object2rexx improvement in
           pipes/utils.nrx
         - optimized ThreadPool startup times.  No setName and only use
           setPriority when its required.
         - made it possible to optimized stage startup time when arguements
           are static.  See TCPDATA, TCPCLIENT & LOOKUP
         - faq.txt enhanced
   0.40  - Released August 14, 1998
         * All pipes MUST be recompiled.  Old pipe class files will stall.
         - OBJ2REXX is depreciated and will be removed, use the REXX stage.
         - added REXX and STRING stages to convert objects entering and leaving
           a stage to rexx or string.  Inorder to avoid nasty class conflicts,
           REXX and STRING are implemented in _rexx and _string.  The compler
           adds the '_' when necessary (any stage can use this feature).
         - fixed an intermitant stall in callpipe (was completing too fast :-)
         - fixed a stall occuring between shortStreams and COMMAND
         - optimized pipe startup time in pipe.class and via the compiler.
         - optimized rc, commit, deadlock, threadpool code
   0.39  - Released August 9, 1998
         - WAIT_COMMIT and WAIT_ANY are now used in the call/addpipe logic
         - callpipe was not notifiing its pipe when ending leading to an
           very intermitant hang.
   0.38  - Released August 3, 1998
         * All your stages must be recompiled.  Recompile your pipes to
           exploit the pipe & thread pool performance improvements.
         - fixed and optimized commit logic.
         - implement a pool for pipes to decrease overhead.
         - implement a pool for threads to decrease overhead.
         - compiler fix to proprogate return codes from stageExits (thanks Jeff).
         - signal StageError('...  in all stageExits modified to
           signal StageError(13,'Error - 'pInfo' - ...
         - UNIQUE stage added by Jeff.  It exploits stageExit.
         - COMMAND stage was not starting its threads correctly.
         - SORTs in different pipes could corrupt each other.  Thanks René
   0.37  - Released July 25, 1998
         * A recompile of pipes using SORT is required
         - added NOEOFBACK, TOTARGET and FRTARGET.
         - removed a protected method from dump(), added arg() to the dump
         - upgraded SORT, sortRexx to exploit IRange and stageExit, optimized
           use, and factored the sort algorthym out of sort/sortRexx.
         - multiple sort stages no longer try to share static variables...
         - the compiler just uses the stage name (not args) when naming stages
   0.36  - Released July 19, 1998
         * A recompile of ALL pipes with stages using IRANGE is required.
           (CHANGE, DEAL, JOINCONT, LOCATE, LOOKUP, PICK, XLATE & ZONE)
         * pipes using NFIND, NLOCATE, STRNFIND or SORT also need to be
           recompiled
         - Added BuildIRangeExit and other methods to an updated IRange
           class.  Using 'zone range stage ...' will be faster than
           'stage range ...' when the range consists of n.c or n-c (s).
         - NFIND, NLOCATE, STRNFIND implemented via stageExit and NOT
         - Fixed bugs in, JUXTAPOSE, FIND, STRFIND, SORT, COMMAND, CHANGE
         - The compiler was not calling stageExit in the correct order when
           several calls were needed to build the stage.  (zone w1 nfind..)
   0.35  - Released July 16, 1998
         - Jeff Hennick pointed out a bugglet that effected LOOKUP, ZONE and
           PICK that could occur with complex ranges, I found another bug in
           strliteral
         - Jeff Hennick updated this doc with information on IRange and DString
   0.35  - Released July 15, 1998
         * A recompile of ALL pipes using ZONE, TCPCLIENT, TCPDATA, PREFIX
           and APPEND is required.
         - prefix and append can now be labeled, tcpclient and tcpdata
           now use a stage, instead of a pipe, to group data.
         - added compiler support for negitive stream numbers.  This is
           intended to be used by stageExit.  See append, prefix, tcpdata
           and tcpclient.
         - Redefined rexxArg() and stageArg() to simplify the compiler.
         - selection stages are no longer defined as final.
         - SelectInput(0) and selectOutput(0) are always called by the
           stage implementation so they can be overridden...
         - Reimplemented ZONE using stageExit, added CASEI using the same
           technique.  In theory NOT could be done the same way but, to
           avoid some recursion problems NOT is staying in the compiler.
         - StageExit modified to allow it to pass back another stage to
           call.  see ZONE, CASEI and NOT.
   0.34  - Released July 11, 1998
         - minor reportEOF(any) logic fix
         - improved command stage, threads used to process stdout and stderr.
           added zone, pad, lookup, pick, upgraded juxtapose, fixed bugs in
           specs & buffer.
         - added pad option to setIRange method
   0.33  - Released July 5, 1998
         - added rexxArg() and stageArg() methods to utils.nrx for use by the
$          compiler to query stages about what they expect their arguments to
           contain.  This allowed the compiler to be simplified.
$        - locate now handles null arguments correctly.  literals now include
           leading blanks.  Thanks for pointing out the problem René.
         - René Jansen contributed the timestamp stage.
         - logic modified to stop output() from getting an EOF when the output
           object has been peeked.  The peek status is also displayed by the
           dump() method and hense by deadlocks.
         - minor specs bug fixes (next.n and nextw.n output specs now work)
         - modified the compiler to invoke stageExit(rexx,rexx) method.  This
           allows stages to generate code and/or change the pipe topology.  See
           specs, append, prefix, change and xnop, in the stages directory.
         - modified StageError in preparation for usage changes.
         - removed the Range class - Jeff's code is better and anything that
           could be done with Range can be done using stageExit.
         - Jeff fixed bugs in change and join and added:
           fblock          joincont        notinside       outside
           inside
   0.32  - Released June 20, 1998
           Jeff updated these stages adding a few new ones too:
           abbrev          between         split           locate
           nlocate         strnfind        strfind         nfind
           find            chop
         - minor docuementation updates
         - the Range class is depreciated and will be removed.  Use the
           replacements Jeff created (see pipes\utils.nrx and stages\).
   0.31  - Released June 17, 1998
         - modified count, drop, take and deal to handle non rexx objects
           when possible
   0.31  - Released June 16, 1998
         - improved eofReport(ANY) logic to trigger when waiting on output
           and a different output stream severs.
         - factored the source for utils.class out of stages so there is
           a class to add (probably static) shared methods for all stages
         - fixed a deadlock that occured between shortStreams and exit
           (severInput)
         - Jeff Hennick updated many stages to work at CMS or near CMS levels.
           append          deal            join            strfrlabel      xlate
           buffer          drop            literal         strliteral
           change          fanin           locate          strtolabel
           console         fanout          split           take
           count           frlabel         strfind         tokenize
           All of Jeff's changes are GNUed.  See CopyLeft.txt in the njpipes
           directory.
   0.30  - Released May 24, 1998
         - fixed logic in core classes to post all pending severs and not
           clear them too early either, this corrects a problem seen on
           Multiprocessor machines.
   0.29  - www page update (docuemention) May 20
         - deadlock section updated
         - installation verification example corrected!
   0.29  - Released May 17, 1998
         - added obj2rexx stage, tolabel stage courtesy of Chuck Moore.
         - enhanced change to support a single range
         - Added setJITCache(Hashtable) method to pipes.  This can be used
           to build a global object cache in programs calling pipes.  The name
           of the Hasttable is passed to pipe/callpipe/addpipe via a cache
           parameter.
         - Added support for reportEof options.  This support is not too
           well tested - some good testcases are needed.
   0.28  - Released May 9, 1998
         - Enhanced parsing in specs (word2.1 would work, word 2.1 would not)
         - Fixed COPY for a NT jit bug, fixed locate so NOT LOCATE would
           work, updated LITERAL not to use more than one exit(rc)
         - Fixed a compiler problem that would hit multistreamed pipes using
           append or prefix.
         - Any options not consumed by njp are passed on to nrc
           and java.  Mainly for use from the command line, use with care
           in .njp files...
         - Fixed shortStreams() so it works correctly when shorting streams
           in a stage with multiple streams.
         - Tested all 8 addpipe forms and fixed runtime to work with all
           test cases
         - modified filternjp to accept *in and *out without additional labels
         - reenabled stop() in exit code...
         - added gate, dam, tokenize, juxtapose and courtesy of Chuck Moore,
           frlabel stages
   0.27  - Released May 3, 1998
         - Automated the generation of in/outStream calls.  For this to work
           the labels need to be of the form *in0: or *out0: where the '0' is
           replaced by the input or output stream to connect to.
         - Fixed compiler/filter problems with stema
         - Tighted range checking code in specs, fixed problem with delimited
           ranges.  Specs was compiling the NetRexx EXIT command...
         - Fixed a problem where output was not see that objects were
           consumed when using sipping pipes...
         - Fixed a problem where severing an output stream did not cause the
           stages stacked on the node's outlist to see the sever
         - Fixed a problem where the stage issuing a callpipe was not seeing
           the called pipe end
         - Added debug option to pipes compiler
         - Repaired commit and added commit levels to dump() method
         - Fixed problems with callpipe servering several outputs, unstacking
           the saved stream was selecting it...
         - Modified tcpclient and tcpdata to use a secondary thread to
           recieve the tcpip inputs.
         - Now keep a referenced object for each pipe/stage so the JIT does
           not throw away its work and call/addpipes in loops work faster.
         - in/outStreamState now return -1 when autocommit is enabled and
           the stream is unused.
   0.26  - Released April 26, 1998
         - Added selection methods to compiler (see getRange in section 4 and
           the locate stage an example#
         - Added the specs stage.  The compiler builds a stage to process the
           specs, reducing overhead.
         - Added tcp/ip stages
         - Fixed problems with severs using addpipe
   0.25  - Optimized some stages using jinsight from www.alphaworks.ibm.com.
           This more that doubled the speed of some stages.
         - fixed bugs in fanin, diskw
         - Added netrexx filters to extract pipes, extended the functions
           of .njp files (multiple pipes in a file and .njp files can now
           contain netrexx code with pipe/callpipe/addpipe)
         - fixed a timing bug in deadlock detection.
         - xlate and sqlselect stages contributed by René Jansen added
   0.24  - Release Feb 98
         - modified the compiler so the syntax of pipes from the command line
           is the same as pipes from .njp files
         - added the sort stage, the sortClass interface and the sortRexx
           example implementation
         - added the timer stage
   0.23  - fixed minor compiler errors (20 Dec 97)
         - not stage modifier added.
         - errors in this page corrected, NT install information added.
         - modified diskr/diskw to use Buffered Streams.
   0.22  - second public release
   0.21  - enabled auto commit, stages start at a commit level of -2 and
           commit to a level of -1 at the first readto, peekto or output.
           nocommit disables the auto commit.  This feature has not been
           completely tested (yet).
         - fixed compiler not to call netrexx if one of its pipes deadlocks
   0.20  - Upgraded to May version of the NetRexx compiler (Thanks Mike!)
           this changed the compiler interface.  NetRexx from May 10 or
           later is now required.
         - nocommit added to _stages, though its a nop for now
         - modified the compiler class to use the May 10th NetRexx compiler
   0.19  - initial public release (4 May 97)


9. Futures

    Planned for the next month or three (pending BUGS! and my time)

    0.xx - make pipe objects java beans.
    0.xx - implement the new StageError/Emsg code in all stages
    0.xx - rewrite the stage class to use notifyAll/wait to pass data and
           interupt to pass flow control info (ie. severs...).  This will
           result in an implementation that is easier to understand and
           maintain.

    Back to Table of Contents


10. A (semi)Formal Definition

    <pipe> = {<pipestages>} <stage> { <sep>|<end> <stage> }

    <pipestages> = <defstage> {<end> <defstage>} <end>

    <defstage> = <pipeinstance>= <pipeclass>({<arguments})

    <sep> = stage seprator (!)

    <end> = end of pipe character (?)

    <stage> = {<pipeasstage> {<sep> nop <sep> <pipeasstage>} }
            | {<label>} { not } <stageclass> {<arguments>}

    <pipeasstage> = {<connector>}.<pipeinstance>.{<connector>}

    <label> = <labelname>: | *<connector>:

$   <arguments> = a string of characters
                 | arg({<index>})

    <stageclass> = the name of a stage .class file

    <pipeclass> = the name of a pipe .class file

    <pipeinstance> = a non numeric string of characters

    <labelname> = a non numeric string of characters

    <connector> = {in | out}{a string of characters}

    <index> = Index of a rexx argument (see calling pipes from NetRexx)

    Back to Table of Contents


11. Commerical Use

    Commercal restrictions are as follows:

    1. Contact information is required, an email address is prefered.

       There are several reasons for this.  The first is that if I stop working on it
       I will make the complete source available and would like to notify sites that
       may be depending on the product.  A second reason is that if ever a better
       implementation of the core classes is developed, or a serious bug is corrected
       I will notify Commerical users.  Your email address will not be redistributed
       without permission.

    2. You are free to redistribute Pipes for Netrexx and Java but cannot charge for
       it.  You can include it, or subsets of it, in products you charge for but must
       reference my site (http://www.cam.org/~tomlins/njpipes.html).

    Back to Table of Contents


12. Trademarks

    Java is a trademark of Sun Microsystems

    Windows NT is a trademark of MicroSoft

    The following terms, are trademarks or registered
    trademarks of IBM Corporation in the United States and/or other countries:

    IBM
    OS/2
    NetRexx
    CMS

    Back to Table of Contents