home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c160 / 1.ddi / TEST / T4MUL.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-22  |  18.1 KB  |  872 lines

  1. /* t4mul.c
  2.  
  3.    (c)Copyright Sequiter Software Inc., 1987-1990. All rights reserved.
  4.  
  5.    Tests Code Base multi-user.
  6. */
  7.  
  8. #include  "p4misc.h"
  9. #include  "d4all.h"
  10. #include  "w4.h"
  11. #include  "u4error.h"
  12.  
  13. #include  <string.h>
  14. #include  <stdlib.h>
  15. #include  <stdio.h>
  16.  
  17. static FIELD  co_fields[] =
  18. {
  19.    { "COMMAND", 'C', 20,0,0 },
  20.    { "PARM", 'C', 8, 0,0},
  21. } ;
  22.  
  23. #define  WORK_WIDTH  11
  24.  
  25. static FIELD  wo_fields[] =
  26. {
  27.    { "WORK", 'C', WORK_WIDTH,0,0 },
  28. } ;
  29.  
  30. static FIELD  result_flds[] =
  31. {
  32.    { "RESULT", 'C', 8,0,0 },
  33. } ;
  34.  
  35. #ifdef LOG
  36. static FIELD  log_flds[] =
  37. {
  38.    { "ID",   'C', 12,0,0 },
  39.    { "LOG1", 'C', 20,0,0 },
  40.    { "LOG2", 'C', 20,0,0 },
  41. } ;
  42. #endif
  43.  
  44. char *log_id_ptr = (char *) 0 ;
  45. int   lo = -1 ;
  46. int   co, wo, re, i_w1, i_w2 ;
  47. long  co_ref,  parm_ref, wo_ref, id_ref, log1_ref, log2_ref, result_ref ;
  48.  
  49. static void  send(char *, char *) ;
  50. static void  int_ret(long,int) ;
  51. static void  ch_base_locked(long,int);
  52. static void  command_sender(void) ;
  53. static void  work_doer(void) ;
  54. static void  d_lock(void) ;
  55. static void  d_seek(void) ;
  56. static void  d_skip(void) ;
  57. static void  d_write(void) ;
  58. static void  d_append(void) ;
  59. static void  d_unlock(void) ;
  60. static void  i_lock(void) ;
  61. static void  sleep(long) ;
  62. static void  d_append_one(void) ;
  63. static int   seek_recs(long) ;
  64. static int   write_recs(long) ;
  65. static int   append_recs(long) ;
  66. static int   skip_recs(long) ;
  67. static int   result_int( int) ;
  68.  
  69. /* Number of Records per Buffer for T4MUL_WO.DBF */
  70. #define  REC_PER_BUF  2L
  71.  
  72. extern void  logger( char *, char *) ;
  73.  
  74. int  first = 1 ;
  75.  
  76. void  logger( char *p1, char *p2 )
  77. {
  78.    int  p_ref ;
  79.  
  80.    if ( d4select(-1) == lo || lo < 0 )  return ;
  81.  
  82.    p_ref =  d4select(lo) ;
  83.    d4lock(-1L,1) ;
  84.  
  85.    if ( first )
  86.    {
  87.       first = 0 ;
  88.       d4zap( 1L, d4reccount() ) ;
  89.    }
  90.  
  91.    if ( log_id_ptr == (char *) 0 )
  92.       f4r_str( id_ref,   "UNKNOWN" ) ;
  93.    else
  94.       f4r_str( id_ref,   log_id_ptr ) ;
  95.    f4r_str( log1_ref, p1 ) ;
  96.    f4r_str( log2_ref, p2 ) ;
  97.    d4append() ;
  98.  
  99.    d4unlock(-1L) ;
  100.    d4select(p_ref) ;
  101. }
  102.  
  103. #ifdef OS2
  104. extern unsigned far pascal DOSSLEEP (
  105.         unsigned long );
  106.    
  107.    static void  sleep( n_ms )
  108.    long  n_ms ;
  109.    {
  110.       DOSSLEEP( (unsigned long) n_ms ) ;
  111.    }
  112. #else
  113.    
  114.    static void  sleep( long n_ms )
  115.    {
  116.       while( n_ms-- > 0 ) ;
  117.    }
  118. #endif
  119.  
  120. main()
  121. {
  122.    int  rc ;
  123.  
  124.    #ifdef NO_HUGE
  125.       #ifdef IS_386
  126.          d4init() ;
  127.       #else
  128.          d4initialize( 4, 4, 20, 1000, 20000L ) ;
  129.       #endif
  130.    #else
  131.       d4init() ;
  132.    #endif
  133.    w4clear(-1) ;
  134.  
  135.    if ( (co = d4use("T4MUL_CO")) < 0 )
  136.    {
  137.       w4( w4row()+1,0, "Creating T4MUL_CO" ) ;
  138.       if ( (co =  d4create( "T4MUL_CO", 2, co_fields, 0)) < 0 )
  139.          w4exit(1) ;
  140.    }
  141.    d4buf_total( 1L, 1, 0 ) ;
  142.    d4buf_unit( 1L ) ;
  143.    co_ref =  f4ref( "COMMAND" ) ;
  144.    parm_ref =  f4ref( "PARM" ) ;
  145.  
  146.    if ( (wo = d4use("T4MUL_WO")) < 0 )
  147.    {
  148.       w4( w4row()+1,0, "Creating T4MUL_WO" ) ;
  149.       if ( (wo =  d4create( "T4MUL_WO", 3, wo_fields, 0)) < 0 )
  150.          w4exit(1) ;
  151.    }
  152.    d4buf_total( 8L, 3, 0 ) ;
  153.    d4buf_unit( REC_PER_BUF ) ;
  154.    wo_ref =  f4ref( "WORK" ) ;
  155.  
  156.    if ( (re = d4use("T4MUL_RE")) < 0 )
  157.    {
  158.       w4( w4row()+1,0, "Creating T4MUL_RE" ) ;
  159.       if ( (re =  d4create( "T4MUL_RE", 1, result_flds, 0)) < 0 )
  160.          w4exit(1) ;
  161.    }
  162.    d4buf_total( 1L, 1, 0 ) ;
  163.    d4buf_unit( 1L ) ;
  164.    result_ref =  f4ref( "RESULT" ) ;
  165.  
  166.    #ifdef LOG
  167.       if ( (lo = d4use("T4MUL_LO")) < 0 )
  168.       {
  169.      w4( w4row()+1,0, "Creating T4MUL_LO" ) ;
  170.      if ( (lo =  d4create( "T4MUL_LO", 3, log_flds, 0)) < 0 )
  171.         w4exit(1) ;
  172.       }
  173.       id_ref   =  f4ref( "ID" ) ;
  174.       log1_ref =  f4ref( "LOG1" ) ;
  175.       log2_ref =  f4ref( "LOG2" ) ;
  176.       logger( "First Log", "" ) ;
  177.    #endif
  178.  
  179.    w4( w4row()+1,0, "Databases Open" ) ;
  180.  
  181.    d4select(co) ;
  182.    if ( (rc = d4lock( -1L, 0)) == -1 )  w4exit(1) ;
  183.    if ( rc == 0 )
  184.    {
  185.       log_id_ptr =  "Commander" ;
  186.       w4( w4row()+1,0, "Commander Session" ) ;
  187.  
  188.       d4select(re) ;
  189.       d4zap( 1L, d4reccount() ) ;
  190.       d4unlock(-1L) ;
  191.  
  192.       d4select(wo) ;
  193.  
  194.       /* Wait Until the 'work' Database has been Locked. */
  195.       for ( ;;)
  196.       {
  197.      if ( (rc = d4lock(-1L, 0)) == -1 )  w4exit(1) ;
  198.      if ( rc != 0 )
  199.      {
  200.         w4( w4row()+1,0, "Lock Detected!" ) ;
  201.         break ;
  202.      }
  203.  
  204.      d4unlock(-1L) ;
  205.  
  206.      w4position( w4row()+1,0) ;
  207.      w4clear(w4row()) ;
  208.      w4( w4row(),0, "Commander - 'T4MUL_WO.DBF' not yet locked by worker." ) ;
  209.      sleep( 50L ) ;
  210.       }
  211.  
  212.       command_sender() ;
  213.       w4clear(-1) ;
  214.       w4( 0,0, "Commander Success" ) ;
  215.    }
  216.    else
  217.    {
  218.       log_id_ptr =  "Worker   " ;
  219.       w4( w4row()+1,0, "Worker Session" ) ;
  220.  
  221.       d4select(wo) ;
  222.       d4zap( 1L, d4reccount()) ;
  223.  
  224.       if ( d4lock(-1L,1) < 0 )   w4exit(1) ;
  225.       w4( w4row()+1,0, "T4MUL_WO.DBF locked." ) ;
  226.  
  227.       i_w1 =  i4index( "T4MUL_W1", "WORK", 0,0) ;
  228.       i_w2 =  i4index( "T4MUL_W2", "WORK", 0,0) ;
  229.  
  230.       work_doer() ; 
  231.       w4clear(-1) ;
  232.       w4( 0,0, "Worker Success" ) ;
  233.    }
  234.       
  235.    d4close_all() ;
  236.  
  237.    w4cursor(w4row()+1,0) ;
  238.    d4init_undo() ;
  239.  
  240.    #ifdef H4TEST
  241.       rc =  h4free_check(32000) ;
  242.       if ( rc != 0 )
  243.          printf( "t4mul:  Error -  %d memory items are not freed !", rc ) ;
  244.    #endif
  245.  
  246.    exit(0) ;
  247. }
  248.  
  249.  
  250. static void send( char *com, char *parm )
  251. {
  252.    int  p_ref ;
  253.  
  254.    w4position( w4row()+2,0) ;
  255.    w4clear( w4row() ) ;
  256. /* w4( w4row(),0, "Press a Char to Send Next Command ... " ) ;
  257.    g4char() ;
  258. */
  259.    w4( w4row(),w4col(), "Sent: " ) ;
  260.    w4out( com ) ;
  261.    w4out( "   Parameter: " ) ;
  262.    w4out( parm ) ;
  263.  
  264.    p_ref =  d4select( co ) ;
  265.    d4lock( -1L, 1 ) ;
  266.  
  267.    d4append_blank() ;
  268.    f4r_str( co_ref, com ) ;
  269.    f4r_str( parm_ref, parm ) ;
  270.  
  271.    d4unlock( -1L ) ;
  272.  
  273.    d4select( p_ref ) ;
  274. }
  275.  
  276. static void  int_ret( long rec, int val )
  277. {
  278.    int  p_ref ;
  279.  
  280.    w4( w4row()+1,0, "Getting Return Record" ) ;
  281.    w4long( w4row(),w4col(), rec, 6) ;
  282.    w4( w4row(),w4col(), " ... " ) ;
  283.  
  284.    p_ref =  d4select( re ) ;
  285.    d4unlock( -1L ) ;
  286.  
  287.    while ( d4reccount() < rec )
  288.       sleep(50L) ; /* 1/20 Second */
  289.  
  290.    d4go( rec ) ;
  291.    if ( f4int(result_ref) != val )
  292.    {
  293.       u4error( 0, "t4mul:  result is unexpected.", (char *) 0 ) ;
  294.       w4exit(1) ;
  295.    }
  296.  
  297.    d4unlock(-1L) ;
  298.    d4select( p_ref ) ;
  299.  
  300.    w4( w4row(),w4col(), "Received" ) ;
  301. }
  302.  
  303. /* Check the locks
  304.    rec_cd -  That Record Should be Locked
  305.           -  If zero, no specific record is locked
  306.  
  307.    file_cd - Neg one and the whole file should be locked.
  308.            - Zero and the reccount byte should be locked.
  309.        - One and nothing is locked except perhaps a record.
  310. */
  311. static void  ch_base_locked( long rec_cd, int file_cd )
  312. {
  313.    int  rc ;
  314.  
  315.    w4( w4row()+1,0, "Checking Database Locks" ) ;
  316.  
  317.    if ( (rc =  d4lock( -1L, 0 )) == -1 )  w4exit(1) ;
  318.    d4unlock( -1L) ;
  319.  
  320.    if ( rc == 0 )
  321.    {
  322.       /* If the file could be locked, 'worker' can have nothing locked. */
  323.       if (rec_cd != 0L  ||  file_cd != 1 )
  324.       {
  325.          u4error( 0, "t4mul:  Lock Error 1", (char *) 0 ) ;
  326.          w4exit(1) ;
  327.       }
  328.    }
  329.  
  330.    if ( (rc =  d4lock( 0L, 0 )) == -1 )  w4exit(1) ;
  331.    d4unlock( -1L ) ;
  332.    /* If record count bytes can be locked, 'worker' cannot have 
  333.       the whole file locked.   In addition, if the record count
  334.       bytes cannot be locked, they better not be unlocked. */
  335.    if ( rc == 0  && file_cd <= 0  ||   rc == -2 && file_cd == 1 )
  336.    {
  337.       u4error( 0, "t4mul: Lock Error 2", (char *) 0 ) ;
  338.       w4exit(1) ;
  339.    }
  340.  
  341.    if ( d4reccount() > 0L )
  342.    {
  343.       if ( (rc =  d4lock( 1L, 0 )) == -1 )  w4exit(1) ;
  344.       d4unlock( -1L ) ;
  345.       /* If record zero can be locked, 'worker' cannot have the whole
  346.          file locked.  If they cannot be locked, they better not be locked. */
  347.       if ( rc == 0 && (file_cd == -1 || rec_cd == 1L)  ||  
  348.            rc == -2 && file_cd != -1 && rec_cd != 1L)
  349.       {
  350.          u4error( 0, "t4mul: Lock Error 3", (char *) 0 ) ;
  351.          w4exit(1) ;
  352.       }
  353.    }
  354.  
  355.    if ( rec_cd > 0L )
  356.    {
  357.       /* If 'worker' has locked the record, we better not be able to lock it. */
  358.       if ( (rc =  d4lock( rec_cd, 0 )) == -1 )  w4exit(1) ;
  359.       d4unlock( -1L ) ;
  360.       if ( rc == 0  )
  361.       {
  362.          u4error( 0, "t4mul: Lock Error 4", (char *) 0 ) ;
  363.          w4exit(1) ;
  364.       }
  365.    }
  366. }
  367.  
  368. static void  command_sender()
  369. {
  370.    long  r ;
  371.    int   rc, i ;
  372.  
  373.    r = 1L ;
  374.  
  375.    /* Wait until the other database is locked.  This
  376.       signals the other session knows it is the 'work' session. */
  377.    d4select( co) ;
  378.    d4zap( 1L, d4reccount() ) ;
  379.    d4select(wo) ;
  380.  
  381.    send( "D4UNLOCK", "-1" ) ;
  382.    int_ret( r++, 0 ) ;
  383.    ch_base_locked( 0L, 1) ;
  384.  
  385.    /* Lock the work database, it will not be unlocked until
  386.       the index files have been created. */
  387.    d4select(wo) ;
  388.    d4lock(-1L, 1) ;
  389.    if ( (i_w1 = i4open("T4MUL_W1")) < 0 )  w4exit(1) ;
  390.    if ( (i_w2 = i4open("T4MUL_W2")) < 0 )  w4exit(1) ;
  391.    d4unlock(-1L) ;
  392.  
  393.    send( "D4LOCK", "0" ) ;
  394.    int_ret( r++, 0 ) ;
  395.    ch_base_locked( 0L, 0) ;
  396.  
  397.    send( "D4UNLOCK", "0" ) ;
  398.    int_ret( r++, 0 ) ;
  399.    ch_base_locked( 0L, 1) ;
  400.  
  401.    send( "D4LOCK", "-1" ) ;
  402.    int_ret( r++, 0 ) ;
  403.    ch_base_locked( 0L, -1) ;
  404.  
  405.    send( "D4UNLOCK", "-1" ) ;
  406.    int_ret( r++, 0 ) ;
  407.    ch_base_locked( 0L, 1) ;
  408.  
  409.  
  410.    send( "I4LOCK", "" ) ;
  411.    int_ret( r++, 0 ) ;
  412.  
  413.    /* Check to make sure the index file is locked. */
  414.    if ( (rc = i4lock( i_w1, 0)) == -1 )  w4exit(1) ;
  415.    if ( rc == 0 )
  416.    {
  417.       u4error( 0, "t4mul:  Index Locking", (char *) 0 ) ;
  418.       w4exit(1) ;
  419.    }
  420.  
  421.    send( "D4UNLOCK", "-1" ) ;
  422.    int_ret( r++, 0 ) ;
  423.    ch_base_locked( 0L, 1) ;
  424.  
  425.    /* Check to make sure the index file is unlocked. */
  426.    if ( (rc = i4lock( i_w1, 0)) == -1 )  w4exit(1) ;
  427.    if ( rc != 0 )
  428.    {
  429.       u4error( 0, "t4mul:  Index Locking", (char *) 0 ) ;
  430.       w4exit(1) ;
  431.    }
  432.    d4unlock(-1L) ;
  433.  
  434.    for ( i=1; i<= 40; i++ )
  435.    {
  436.       long  count ;
  437.  
  438.       send( "APPEND ONE", "1" ) ;
  439.       int_ret( r++, i ) ;
  440.  
  441.       count =  d4reccount() ;
  442.       if ( count != (long) i )
  443.       {
  444.          u4error( 0, "t4mul:  Count", (char *) 0 ) ;
  445.          w4exit(1) ;
  446.       }
  447.    }
  448.  
  449.    send( "D4UNLOCK", "-1" ) ;
  450.    int_ret( r++, 0 ) ;
  451.    ch_base_locked( 0L, 1) ;
  452.  
  453.    for ( i=1; i<= 40; i++ )
  454.    {
  455.       d4go( (long) i ) ;
  456.       if ( f4long( wo_ref) != (long) i )
  457.       {
  458.          u4error( 0, "t4mul:  Append Check", (char *) 0 ) ;
  459.          w4exit(1) ;
  460.       }
  461.    }
  462.    d4zap(1L, d4reccount() ) ;
  463.    d4unlock(-1L) ;
  464.  
  465.    send( "D4APPEND", "20" ) ;
  466.    append_recs(20L) ;
  467.    int_ret( r++, 0 ) ;
  468.  
  469.    if ( d4reccount() != 40 )
  470.    {
  471.       u4error( 0, "t4mul:  Wrong Count", (char *) 0 ) ;
  472.       w4exit(1) ;
  473.    }
  474.  
  475.    send( "D4LOCK", "0" ) ;
  476.    int_ret( r++, 0 ) ;
  477.    ch_base_locked( 0L, 0) ;
  478.  
  479.    send( "D4LOCK", "5" ) ;
  480.    int_ret( r++, 0 ) ;
  481.    ch_base_locked( 5L, 0) ;
  482.  
  483.    send( "D4LOCK", "2" ) ;
  484.    int_ret( r++, 0 ) ;
  485.    ch_base_locked( 2L, 0) ;
  486.  
  487.    send( "D4UNLOCK", "1" ) ;
  488.    int_ret( r++, 0 ) ;
  489.    ch_base_locked( 0L, 0) ;
  490.  
  491.    send( "D4LOCK", "5" ) ;
  492.    int_ret( r++, 0 ) ;
  493.    ch_base_locked( 5L, 0) ;
  494.  
  495.    send( "D4UNLOCK", "-1" ) ;
  496.    int_ret( r++, 0 ) ;
  497.    ch_base_locked( 0L, 1) ;
  498.  
  499.  
  500.    /* Test Dirty Read. */
  501.    send( "D4LOCK", "-1" ) ;
  502.    int_ret( r++, 0 ) ;
  503.    ch_base_locked( 0L, -1) ;
  504.  
  505.    d4lock_code( 2) ;
  506.    if ( d4go(5L) != 0 )
  507.    {
  508.       u4error( 0, "t4mul:  Dirty Read", (char *) 0 ) ;
  509.       w4exit(1) ;
  510.    }
  511.    if ( f4long( wo_ref) != 5L )
  512.    {
  513.       u4error( 0, "t4mul:  Dirty Read 2", (char *) 0 ) ;
  514.       w4exit(1) ;
  515.    }
  516.  
  517.    d4lock_code( 1) ;
  518.  
  519.    /* Test Lock Wait. */
  520.    d4lock_wait( 0) ;
  521.    if ( d4go(5L) != -2 )
  522.    {
  523.       u4error( 0, "t4mul:  Lock Wait", (char *) 0 ) ;
  524.       w4exit(1) ;
  525.    }
  526.    d4lock_wait( 1) ;
  527.  
  528.    send( "D4SKIP", "1" ) ;
  529.    skip_recs(-1L) ;
  530.    int_ret( r++, 0 ) ;
  531.  
  532.    send( "D4WRITE", "20" ) ; /* Write Records 1 through 4 many times. */
  533.    write_recs(-20L) ;       /* Write Records Backwards. */
  534.    int_ret( r++, 0 ) ;
  535.  
  536.    send( "D4WRITE", "20" ) ; /* Write Records 1 through 4 many times. */
  537.    skip_recs(-1L) ;
  538.    int_ret( r++, 0 ) ;
  539.  
  540.    send( "D4SEEK", "20" ) ; 
  541.    skip_recs(-1L) ;
  542.    int_ret( r++, 0 ) ;
  543.  
  544.    send( "D4SEEK", "-20" ) ; 
  545.    write_recs(20L) ;
  546.    int_ret( r++, 0 ) ;
  547.  
  548.    if ( i4check( i_w1) != 0 )
  549.    {
  550.       u4error( 0, "t4mul:  Check 1", (char *) 0 ) ;
  551.       w4exit(1) ;
  552.    }
  553.  
  554.    if ( i4check( i_w2) != 0 )
  555.    {
  556.       u4error( 0, "t4mul:  Check 2", (char *) 0 ) ;
  557.       w4exit(1) ;
  558.    }
  559.  
  560.    send( "DONE", "" ) ;
  561. }
  562.  
  563.  
  564. static int  seek_recs( long n )
  565. {
  566.    long  i ;
  567.    long  on_rec, direc ;
  568.    int   r_col ;
  569.  
  570.    direc = 1L ;
  571.    if ( n < 0 )
  572.    {
  573.       direc = -1L ;
  574.       n = -n ;
  575.    }
  576.  
  577.    w4( w4row()+1, 0, "Seek Number Recs:" ) ;
  578.    w4long( w4row(),w4col(), n, 6) ;
  579.  
  580.    w4( w4row(),w4col()+4, "Seeking Record:" ) ;
  581.    r_col =  w4col() ;
  582.  
  583.    for ( i = on_rec = 1L; i<= n; i++)
  584.    {
  585.       char buf[100] ;
  586.  
  587.       c4ltoa( on_rec, buf, f4width(wo_ref) ) ;
  588.       if ( d4seek_str(buf) != 0 )  
  589.          w4exit(1) ;
  590.       if ( d4recno() != on_rec )
  591.       {
  592.          u4error( 0, "t4mul: d4seek_double", (char *) 0 ) ;
  593.          w4exit(1) ;
  594.       }
  595.  
  596.       w4long( w4row(),r_col, on_rec, 6 ) ;
  597.  
  598.       on_rec += direc ;
  599.       if ( on_rec < 1L )
  600.          on_rec =  d4reccount() ;
  601.       if ( on_rec > d4reccount())
  602.          on_rec =  1L ;
  603.  
  604.       d4unlock(-1L) ;
  605.    }
  606.  
  607.    return 0 ;
  608. }
  609.  
  610.  
  611. static int  write_recs( long n )
  612. {
  613.    long  i ;
  614.    long  on_rec, direc ;
  615.    int   i_col, r_col ;
  616.  
  617.    w4( w4row()+1, 0, "Writing Records   Itteration:" ) ;
  618.    i_col =  w4col() ;
  619.  
  620.    w4( w4row(),w4col()+10, "Record:" ) ;
  621.    r_col =  w4col() ;
  622.  
  623.    direc = 1L ;
  624.    if ( n < 0 )
  625.    {
  626.       direc = -1L ;
  627.       n = -n ;
  628.    }
  629.  
  630.    for ( on_rec = i=1L; i<= n; on_rec += direc, i++)
  631.    {
  632.       if ( on_rec < 0L )  on_rec =  20L ;
  633.       if ( on_rec > 20L ) on_rec = 1L ;
  634.  
  635.       w4long( w4row(),i_col, i, 6 ) ;
  636.       w4long( w4row(),r_col, on_rec, 6 ) ;
  637.  
  638.       d4go( on_rec ) ;
  639.       f4r_long( wo_ref, on_rec ) ;
  640.       d4unlock(-1L) ;
  641.    }
  642.    return 0 ;
  643. }
  644.  
  645.  
  646. static void  d_append_one()
  647. {
  648.    w4( w4row()+2,0, "Append One Next" ) ;
  649.  
  650.    f4r_long( wo_ref, d4reccount()+1L ) ;
  651.    if ( d4append() < 0 )
  652.       w4exit(1) ;
  653.  
  654.    d4unlock(-1L ) ;
  655.  
  656.    w4( w4row()+1,w4col(), "New Count:" ) ;
  657.    w4long( w4row(),w4col(), d4reccount(), 6 ) ;
  658.  
  659.    result_int( (int) d4reccount() ) ;
  660. }
  661.  
  662.  
  663. static int  append_recs( long n )
  664. {
  665.    int  c ;
  666.    long i ;
  667.  
  668.    w4( w4row()+1,0, "Appending" ) ;  w4long( w4row(),w4col(), n, 6 ) ;
  669.    c =  w4col() ;
  670.    
  671.    for ( i=1L; i<= n; i++ )
  672.    {
  673.       w4long( w4row(),c, i, 6 ) ;
  674.  
  675.       if ( d4append_blank() < 0 ) 
  676.          w4exit(1) ;
  677.  
  678.       f4r_long( wo_ref, d4recno() ) ;
  679.       d4unlock(-1L) ;
  680.  
  681.       sleep(50L) ;
  682.    }
  683.  
  684.    if ( i4check(i_w1) != 0 )
  685.       w4exit(1) ;
  686.    if ( i4check(i_w2) != 0 )
  687.       w4exit(1) ;
  688.  
  689.    d4unlock(-1L) ;
  690.  
  691.    return 0 ;
  692. }
  693.  
  694.  
  695. static int  skip_recs( long direc )
  696. {
  697.    int  c ;
  698.  
  699.    w4( w4row()+1,0, "Skipping Direction: " ) ;
  700.    w4long( w4row(),w4col(), direc, 6 ) ;
  701.    w4( w4row(),w4col(), "   Record On:" ) ;
  702.    c =  w4col() ;
  703.  
  704.    d4select( wo ) ;
  705.  
  706.    if ( direc < 0 )
  707.    {
  708.       direc =  -1L ;
  709.       if ( d4bottom() != 0 )
  710.       {
  711.          u4error( 0, "t4mul", (char *) 0 ) ;
  712.          w4exit(1) ;
  713.       }
  714.    }
  715.    else
  716.    {
  717.       direc =  1L ;
  718.       if ( d4top() != 0 )
  719.       {
  720.          u4error( 0, "t4mul", (char *) 0 ) ;
  721.          w4exit(1) ;
  722.       }
  723.    }
  724.  
  725.    for(;;)
  726.    {
  727.       w4long( w4row(),c, d4recno(), 6) ;
  728.  
  729.       if ( d4skip(direc) < 0 )
  730.          if ( !d4bof() && !d4eof() )
  731.          {
  732.             u4error( 0, "t4mul", (char *) 0 ) ;
  733.             w4exit(1) ;
  734.          }
  735.  
  736.       if ( f4long( wo_ref) != d4recno() )
  737.          if ( ! d4eof() )
  738.          {
  739.             u4error( 0, "t4mul", (char *) 0 ) ;
  740.             w4exit(1) ;
  741.          }
  742.  
  743.       d4unlock(-1L) ;
  744.  
  745.       if ( d4bof() || d4eof() )
  746.       {
  747.          if ( d4recno() != 1L && d4recno() != d4reccount()+1L )
  748.          {
  749.             u4error( 0, "t4mul", (char *) 0 ) ;
  750.             w4exit(1) ;
  751.          }
  752.      return 0 ;
  753.       }
  754.    }
  755. }
  756.  
  757.  
  758. static int result_int( int i )
  759. {
  760.    d4select( re ) ;
  761.    if ( d4lock( -1L, 1) < 0 )  w4exit(1) ;
  762.    d4append_blank() ;
  763.    f4r_int( result_ref, i ) ;
  764.    d4unlock(-1L) ;
  765.  
  766.    return i ;
  767. }
  768.  
  769. static void  d_lock()
  770. {
  771.    result_int( d4lock(f4long(parm_ref),1)) ;
  772. }
  773.  
  774. static void  d_unlock()
  775. {
  776.    result_int( d4unlock(f4long(parm_ref))) ;
  777. }
  778.  
  779. static void  d_seek()
  780. {
  781.    result_int( seek_recs(f4long(parm_ref))) ;
  782. }
  783.  
  784. static void  d_skip()
  785. {
  786.    result_int( skip_recs(f4long(parm_ref))) ;
  787. }
  788.  
  789. static void  d_write()
  790. {
  791.    result_int( write_recs(f4long(parm_ref))) ;
  792. }
  793.  
  794. static void  d_append()
  795. {
  796.    result_int( append_recs(f4long(parm_ref))) ;
  797. }
  798.  
  799. static void  i_lock()
  800. {
  801.    result_int( i4lock( i_w1,1)) ;
  802. }
  803.  
  804. typedef struct  list_st
  805. {
  806.    char work[WORK_WIDTH] ;
  807.    void  (*f)(void) ;
  808. }  LIST ;
  809.  
  810.  
  811. LIST list[] = 
  812. {
  813.    { "D4LOCK    ", d_lock },
  814.    { "D4UNLOCK  ", d_unlock },
  815.    { "D4SEEK    ", d_seek },
  816.    { "D4SKIP    ", d_skip },
  817.    { "D4WRITE   ", d_write},
  818.    { "D4APPEND  ", d_append},
  819.    { "I4LOCK    ", i_lock},
  820.    { "APPEND ONE", d_append_one},
  821.    { "", 0 },
  822. } ;
  823.  
  824. static void work_doer()
  825. {
  826.    long co_rec ;
  827.    int   i ;
  828.  
  829.    d4select( co ) ;
  830.    d4lock(-1L,1 ) ;
  831.    d4unlock( -1L ) ;
  832.  
  833.    d4select( wo ) ;
  834.  
  835.    for ( co_rec = 1L;;)
  836.    {
  837.       /* Get a Command */
  838.       d4select(co) ;
  839.       if ( d4reccount() < co_rec )
  840.       {
  841.          sleep(50L) ;  /* 1/20 Sec */
  842.      continue ;
  843.       }
  844.  
  845.       d4go( co_rec++ ) ;
  846.       d4unlock(-1L) ;
  847.  
  848.       w4( w4row()+2,0, "Received Command: " ) ;
  849.       w4out( f4str(co_ref) ) ;
  850.       w4out( "  Parameter:" ) ;
  851.       w4out( f4str(parm_ref) ) ;
  852.  
  853.       for ( i=0;; i++ )
  854.          if ( list[i].work[0] == '\0' )
  855.      {
  856.         if ( memcmp("DONE", f4ptr(co_ref), 4) == 0 )
  857.            return ;
  858.         u4error( 0, "Unrecognized Command", f4str(co_ref), (char *) 0 ) ;
  859.             w4exit(1) ;
  860.      }
  861.      else
  862.      {
  863.         if ( memcmp( list[i].work, f4ptr(co_ref), sizeof(list->work)-1) == 0)
  864.         {
  865.                d4select(wo) ;
  866.            (*list[i].f)() ;
  867.            break ;
  868.         }
  869.      }
  870.    }
  871. }
  872.