home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / diverses / text_cla / wfl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-12  |  19.3 KB  |  932 lines

  1. /******************************************************************************
  2. *+
  3. ** Module Name:   WFL.C
  4. ** 
  5. ** Description:   Workflow extensions to
  6. **                MOS:
  7. **
  8. **                Multi-tasking
  9. **                Operating
  10. **                System
  11. **                Simulation
  12. **
  13. **
  14. ** Written by:  John Tal
  15. **
  16. **
  17. **
  18. ** Modification History:
  19. **
  20. ** Date          Programmer      Mod#     Modification
  21. ** ---------------------------------------------------------------------------
  22. ** 04-JUL-1991   J. Tal          V1.0-000 New
  23. **
  24. *-
  25. */
  26.  
  27.  
  28. #ifdef C_ANSI
  29. #include <string.h>
  30. #include <stdlib.h>
  31. #include <stdio.h>
  32. #endif
  33.  
  34.  
  35. #include <memlib.h>
  36. #include <time.h>
  37.  
  38.  
  39. #include <mos.h>
  40.  
  41. #include <wfl.h>
  42.  
  43.  
  44. /*
  45. **   Workflow Variables
  46. */
  47.  
  48. #ifdef TEST
  49. #ifdef C_ANSI
  50. SHORT ProcEndMain(PROC_P pstProc);
  51. VOID ProcEndInit(VOID);
  52. VOID ProcProcMain(PROC_P pstProc);
  53. VOID ProcProcInit(VOID);
  54. VOID ProcLoadMain(PROC_P pstProc);
  55. VOID ProcLoadInit(VOID);
  56. #else
  57. SHORT ProcEndMain();
  58. VOID ProcEndInit();
  59. VOID ProcProcMain();
  60. VOID ProcProcInit();
  61. VOID ProcLoadMain();
  62. VOID ProcLoadInit();
  63. #endif
  64. #endif
  65.  
  66.  
  67.  
  68. #ifdef TEST
  69.  
  70. struct JOB_S           /* a dummy 'job' to process */
  71. {
  72.      CHAR  szTitle[32];
  73.      CHAR  szStatus[32]; 
  74. };
  75.  
  76. typedef struct JOB_S JOB_T;
  77. typedef JOB_T * JOB_P;
  78.  
  79.  
  80. JOB_T stJob1;    /* some jobs */
  81. JOB_T stJob2;
  82. JOB_T stJob3;
  83. JOB_T stJob4;
  84.  
  85. #endif
  86.  
  87.  
  88. TNODE_P   pstWorkTree = NULL;  /* the job tree */
  89.  
  90. WORK_FLOW_T stLoadProc; 
  91. WORK_FLOW_T stProcProc; 
  92. WORK_FLOW_T stEndProc;
  93.  
  94. LLIST_P   pstLoadProfile = NULL;  /* LIST of workflow for each process */
  95. LLIST_P   pstProcProfile = NULL;
  96. LLIST_P   pstEndProfile = NULL;
  97.  
  98. LONG   glJobCount = 0;
  99.  
  100. WORK_ITEM_T  stWorkItem1;      /* data to be processed */
  101. WORK_ITEM_T  stWorkItem2;
  102. WORK_ITEM_T  stWorkItem3;
  103. WORK_ITEM_T  stWorkItem4;
  104.  
  105. #define  WFL_STD_SLEEP_SECS  3
  106.  
  107.  
  108.  
  109. /* ******************************************************************** */
  110. /* *********** TEST CODE ********************************************** */
  111. /* ******************************************************************** */
  112.  
  113. /*
  114. **   Wfl Main
  115. */
  116.  
  117. #ifdef TEST
  118.  
  119. main()
  120. {
  121.    C_DEF_MODULE("WflMain")
  122.  
  123.    C_STATUS = MosInit();
  124.  
  125.     /*
  126.     **  Initialize each job
  127.     */
  128.  
  129.     stWorkItem1.sState = 100;
  130.     strcpy(stWorkItem1.szId,"Job1");
  131.     strcpy(stWorkItem1.szKey,"No Owner");
  132.     stWorkItem1.fLocked = C_FALSE;
  133.     stWorkItem1.pvData = (PVOID) &stJob1;
  134.  
  135.  
  136.     stWorkItem2.sState = 100;
  137.     strcpy(stWorkItem2.szId,"Job2");
  138.     strcpy(stWorkItem2.szKey,"No Owner");
  139.     stWorkItem2.fLocked = C_FALSE;
  140.     stWorkItem2.pvData = (PVOID) &stJob2;
  141.  
  142.  
  143.     stWorkItem3.sState = 100;
  144.     strcpy(stWorkItem3.szId,"Job3");
  145.     strcpy(stWorkItem3.szKey,"No Owner");
  146.     stWorkItem3.fLocked = C_FALSE;
  147.     stWorkItem3.pvData = (PVOID) &stJob3;
  148.  
  149.  
  150.     stWorkItem4.sState = 100;
  151.     strcpy(stWorkItem4.szId,"Job4");
  152.     strcpy(stWorkItem4.szKey,"No Owner");
  153.     stWorkItem4.fLocked = C_FALSE;
  154.     stWorkItem4.pvData = (PVOID) &stJob4;
  155.  
  156.     /*
  157.     **  Add each job to master list in tree
  158.     */
  159.  
  160.     WflJobAdd(&pstWorkTree,&stWorkItem1);
  161.     WflJobAdd(&pstWorkTree,&stWorkItem2);
  162.     WflJobAdd(&pstWorkTree,&stWorkItem3);
  163.     WflJobAdd(&pstWorkTree,&stWorkItem4);
  164.  
  165.  
  166.    /*
  167.    **  Load up some processes, all use the MosGenericProc as their
  168.    **  code.   This could be modified for experimentation to
  169.    **  be other processes modeled after MosGenericProc but
  170.    **  with specialized functions
  171.    */
  172.  
  173.    ProcLoadInit();
  174.    ProcProcInit();
  175.    ProcEndInit();
  176.  
  177.    C_STATUS = MosProcCreate(ProcLoadMain,"PROC_LOAD",10);
  178.    C_STATUS = MosProcCreate(ProcProcMain,"PROC_PROC",10);
  179.    C_STATUS = MosProcCreate(ProcEndMain,"PROC_END",10);
  180.  
  181.  
  182.    C_STATUS = MosScheduler();
  183.  
  184.    C_RETURN
  185. }
  186.  
  187.  
  188. /* ******************************************************************** */
  189. /* ******************************************************************** */
  190. /* ******************************************************************** */
  191.  
  192.  
  193.  
  194. #ifdef C_ANSI
  195. VOID
  196. ProcLoadInit(VOID)
  197. #else
  198. VOID
  199. ProcLoadInit()
  200. #endif
  201. {
  202.     strcpy(stLoadProc.szKey,"LOAD_PROC");
  203.     stLoadProc.sTrnStates = 4;
  204.     stLoadProc.sTrnState[WFL_SEL_STATE] = 100;  /* Selection */
  205.     stLoadProc.sTrnState[WFL_ACT_STATE] = 101;  /* Activation */
  206.     stLoadProc.sTrnState[WFL_TRN_STATE + 0] = 200;  /* successful completion */
  207.     stLoadProc.sTrnState[WFL_TRN_STATE + 1] = 900;  /* error */
  208.  
  209.     WflProAdd(&pstLoadProfile,&stLoadProc);
  210.  
  211. }
  212.  
  213.  
  214. #ifdef C_ANSI
  215. VOID
  216. ProcLoadMain(PROC_P pstProc)
  217. #else
  218. VOID
  219. ProcLoadMain(pstProc)
  220. PROC_P  pstProc;
  221. #endif
  222. {
  223.    C_DEF_MODULE("ProcLoadMain")
  224.  
  225.    WORK_FLOW_P  pstWorkNdx;
  226.    WORK_ITEM_P  pstWorkItem;
  227.    JOB_P       pstJob;
  228.  
  229.    static SHORT sTrys = 0;
  230.  
  231.  
  232.    C_STATUS = WflJobSelect(pstWorkTree,
  233.                         pstLoadProfile,
  234.                         &pstWorkNdx,
  235.                         &pstWorkItem,
  236.                         (PVOID *) &pstJob);
  237.  
  238.    if(!C_STATUS)
  239.    {
  240.  
  241.       WflJobTrans(&pstWorkTree,
  242.                     pstWorkItem,
  243.                     pstWorkNdx,
  244.                     WFL_ACT_STATE,
  245.                     C_FALSE);  /* mark in process */
  246.    
  247.       sprintf(pstJob -> szTitle,"Job %d Loaded at %d\n",
  248.                 glJobCount,
  249.                 MosCurTime());
  250.    
  251.       glJobCount++;
  252.    
  253.          
  254.       WflJobTrans(&pstWorkTree,
  255.                      pstWorkItem,
  256.                      pstWorkNdx,
  257.                      WFL_TRN_STATE+WFL_TRN_OK,C_TRUE);  /* mark ok */
  258.    
  259.       C_STATUS = MosReschedReady(pstProc);
  260.  
  261.    }
  262.    else
  263.    {
  264.       sTrys++;
  265.       if(sTrys > 2)
  266.       {
  267.          C_STATUS = MosProcTerm(pstProc);
  268.          C_LEAVE(C_OK);
  269.       }
  270.       pstProc -> lWakeTime = MosCurTime() + WFL_STD_SLEEP_SECS;
  271.       C_STATUS = MosSleep(pstProc);
  272.    }
  273.  
  274. C_MODULE_EXIT:
  275.   
  276.    ;
  277.  
  278. }
  279.  
  280.  
  281. #ifdef C_ANSI
  282. VOID
  283. ProcProcInit(VOID)
  284. #else
  285. VOID
  286. ProcProcInit()
  287. #endif
  288. {
  289.     strcpy(stProcProc.szKey,"PROC_PROC");
  290.     stProcProc.sTrnStates = 4;
  291.     stProcProc.sTrnState[0] = 200;  /* Selection */
  292.     stProcProc.sTrnState[1] = 201;  /* Activation */
  293.     stProcProc.sTrnState[2] = 300;  /* successful completion */
  294.     stProcProc.sTrnState[4] = 901;  /* error */
  295.  
  296.     WflProAdd(&pstProcProfile,&stProcProc);
  297. }
  298.  
  299.  
  300. #ifdef C_ANSI
  301. VOID
  302. ProcProcMain(PROC_P pstProc)
  303. #else
  304. VOID
  305. ProcProcMain(pstProc)
  306. PROC_P pstProc;
  307. #endif
  308. {
  309.    C_DEF_MODULE("ProcProcMain")
  310.  
  311.    WORK_FLOW_P  pstWorkNdx;
  312.    WORK_ITEM_P  pstWorkItem;
  313.    JOB_P       pstJob;
  314.  
  315.    static SHORT sTrys = 0;
  316.  
  317.  
  318.    C_STATUS = WflJobSelect(pstWorkTree,
  319.                         pstProcProfile,
  320.                         &pstWorkNdx,
  321.                         &pstWorkItem,
  322.                         (PVOID *) &pstJob);
  323.    if(!C_STATUS)
  324.    {
  325.  
  326.       WflJobTrans(&pstWorkTree,
  327.                     pstWorkItem,
  328.                     pstWorkNdx,
  329.                     WFL_ACT_STATE,
  330.                     C_FALSE);  /* mark in process */
  331.    
  332.       sprintf(pstJob -> szStatus,"Job Processed at %d\n",
  333.               MosCurTime());
  334.    
  335.          
  336.       WflJobTrans(&pstWorkTree,
  337.                   pstWorkItem,
  338.                   pstWorkNdx,
  339.                   WFL_TRN_STATE+WFL_TRN_OK,C_TRUE);  /* mark ok */
  340.    
  341.       C_STATUS = MosReschedReady(pstProc);
  342.    }
  343.    else
  344.    {
  345.       sTrys++;
  346.       if(sTrys > 2)
  347.       {
  348.          C_STATUS = MosProcTerm(pstProc);
  349.          C_LEAVE(C_OK);
  350.       }
  351.       pstProc -> lWakeTime = MosCurTime() + WFL_STD_SLEEP_SECS;
  352.       C_STATUS = MosSleep(pstProc);
  353.    }
  354.    
  355. C_MODULE_EXIT:
  356.   
  357.    ;
  358. }
  359.  
  360.  
  361. #ifdef C_ANSI
  362. VOID
  363. ProcEndInit(VOID)
  364. #else
  365. VOID
  366. ProcEndInit()
  367. #endif
  368. {
  369.     strcpy(stEndProc.szKey,"END_PROC");
  370.     stEndProc.sTrnStates = 4;
  371.     stEndProc.sTrnState[0] = 300;  /* Selection */
  372.     stEndProc.sTrnState[1] = 301;  /* Activation */
  373.     stEndProc.sTrnState[2] = 400;  /* successful completion */
  374.     stEndProc.sTrnState[4] = 902;  /* error */
  375.  
  376.     WflProAdd(&pstEndProfile,&stEndProc);
  377.  
  378. }
  379.  
  380.  
  381. #ifdef C_ANSI
  382. SHORT
  383. ProcEndMain(PROC_P pstProc)
  384. #else
  385. SHORT
  386. ProcEndMain(pstProc)
  387. PROC_P pstProc;
  388. #endif
  389. {
  390.    C_DEF_MODULE("EndProcMain")
  391.  
  392.    WORK_FLOW_P  pstWorkNdx;
  393.    WORK_ITEM_P  pstWorkItem;
  394.    JOB_P       pstJob;
  395.    static SHORT sTrys = 0;
  396.  
  397.    
  398.  
  399.  
  400.    C_STATUS = WflJobSelect(pstWorkTree,
  401.                         pstEndProfile,
  402.                         &pstWorkNdx,
  403.                         &pstWorkItem,
  404.                         (PVOID *) &pstJob);
  405.  
  406.    if(!C_STATUS)
  407.    {
  408.       WflJobTrans(&pstWorkTree,
  409.                     pstWorkItem,
  410.                     pstWorkNdx,
  411.                     WFL_ACT_STATE,
  412.                     C_FALSE);  /* mark in process */
  413.    
  414.       printf("%s Ended at %d\n",  pstJob -> szTitle, MosCurTime());
  415.    
  416.          
  417.       WflJobTrans(&pstWorkTree,
  418.                   pstWorkItem,
  419.                   pstWorkNdx,
  420.                   WFL_TRN_STATE+WFL_TRN_OK,C_TRUE);  /* mark ok */
  421.    
  422.       C_STATUS = MosReschedReady(pstProc);
  423.    } 
  424.    else
  425.    {
  426.       sTrys++;
  427.       if(sTrys > 2)
  428.       {
  429.          C_STATUS = MosProcTerm(pstProc);
  430.          C_LEAVE(C_OK);
  431.       }
  432.  
  433.       pstProc -> lWakeTime = MosCurTime() + WFL_STD_SLEEP_SECS;
  434.       C_STATUS = MosSleep(pstProc);
  435.  
  436.      /* glSleepings++; */  /* must have some way to know when to shutdown */
  437.    }
  438.  
  439. C_MODULE_EXIT:
  440.   
  441.    ;
  442.  
  443.    C_RETURN
  444.  
  445. }
  446.  
  447.  
  448. #endif
  449.  
  450. /* end of testing code */
  451.  
  452.  
  453. /* ******************************************************************** */
  454. /* *********** WFL FUNCTIONS ****************************************** */
  455. /* ******************************************************************** */
  456.  
  457. /*
  458. **  WflProAdd
  459. **
  460. **  Adds a profile for a process to the process' profile list
  461. */
  462.  
  463. #ifdef C_ANSI
  464. SHORT APIENTRY
  465. WflProAdd(LLIST_PP ppstProfile, WORK_FLOW_P pstWorkFlow)
  466. #else
  467. SHORT APIENTRY
  468. WflProAdd(ppstProfile,pstWorkFlow)
  469. LLIST_PP ppstProfile;
  470. WORK_FLOW_P  pstWorkFlow;
  471. #endif
  472. {
  473.    C_DEF_MODULE("WflProAdd")
  474.  
  475.    LLIST_P  pstProfile;
  476.    LLIST_P  pstList;
  477.    LLIST_P  pstTail;
  478.  
  479.    pstProfile = *ppstProfile;
  480.  
  481.    C_STATUS = MemLstAllocMember(&pstList);
  482.  
  483.    pstList -> pvData = (PVOID) pstWorkFlow;
  484.  
  485.    if(pstProfile != NULL)
  486.    {
  487.  
  488.      C_STATUS = MemLstFindTailMember(pstProfile,&pstTail);
  489.  
  490.      C_STATUS = MemLstAddAfterMember(pstTail,pstList);
  491.    }
  492.    else
  493.      pstProfile = pstList;
  494.  
  495.  
  496.    *ppstProfile = pstProfile;
  497.  
  498.    C_RETURN
  499.  
  500. }
  501.  
  502.  
  503.  
  504. /*
  505. **  Add another job.
  506. **  Each workflow_T is in a linked-list off of a single binary tree node
  507. */
  508.  
  509. #ifdef C_ANSI
  510. SHORT APIENTRY
  511. WflJobAdd(TNODE_PP ppstWorkTree,WORK_ITEM_P pstWorkItem)
  512. #else
  513. SHORT APIENTRY
  514. WflJobAdd(ppstWorkTree,pstWorkItem)
  515. TNODE_PP ppstWorkTree;
  516. WORK_ITEM_P pstWorkItem;
  517. #endif
  518. {
  519.     C_DEF_MODULE("WflJobAdd")
  520.  
  521.     TNODE_P  pstWorkTree;
  522.     TNODE_P  pstNode;
  523.     LLIST_P  pstList;
  524.     LLIST_P  pstNewList;
  525.     LLIST_P  pstLastList;
  526.  
  527.  
  528.     pstWorkTree = *ppstWorkTree;
  529.  
  530.     C_STATUS = MemTreFindNode(pstWorkTree,
  531.                               (PVOID) &pstWorkItem -> sState,
  532.                               CompareState,
  533.                               &pstNode);
  534.  
  535.     if(pstNode == NULL)
  536.     {
  537.  
  538. #if TEST
  539.    printf("WflJobAdd:   Adding entry for state %d\n",
  540.            pstWorkItem -> sState);
  541. #endif
  542.  
  543.        /*
  544.        **  Must add entry for this state
  545.        */
  546.  
  547.        C_STATUS = MemTreAllocNode(&pstNode);
  548.  
  549.        C_STATUS = MemLstAllocMember(&pstList);
  550.  
  551.        pstList -> pvData = (PVOID) pstWorkItem;
  552.  
  553.  
  554.  
  555.        pstNode -> pvData = (PVOID) pstList;
  556.  
  557.        C_STATUS = MemTreInsertNode(pstWorkTree,
  558.                                    pstNode,
  559.                                    CompareNodeState,
  560.                                    &pstWorkTree);
  561.  
  562.     }
  563.     else
  564.     {   
  565. #if TEST
  566.    printf("WflJobAdd:   Appending entry for state %d\n",
  567.            pstWorkItem -> sState);
  568. #endif
  569.  
  570.        /*
  571.        **  Find current llist
  572.        */
  573.  
  574.        pstList = (LLIST_P) pstNode -> pvData;
  575.  
  576.        /*
  577.        **  Make new member
  578.        */
  579.  
  580.        C_STATUS = MemLstAllocMember(&pstNewList);
  581.  
  582.        pstNewList -> pvData = (PVOID) pstWorkItem;
  583.  
  584.        /*
  585.        **  Find last one of current list
  586.        */
  587.  
  588.        C_STATUS = MemLstFindTailMember(pstList,&pstLastList);
  589.  
  590.        /*
  591.        **  Add new one after current last one
  592.        **  Maintains FIFO ordering
  593.        */
  594.  
  595.        C_STATUS = MemLstAddAfterMember(pstLastList,pstNewList);
  596.  
  597.     }
  598.  
  599.     *ppstWorkTree = pstWorkTree;
  600.  
  601.     C_RETURN
  602. }
  603.  
  604.  
  605.  
  606.  
  607. /*
  608. **  WflJobSelect, select a job to work on
  609. */
  610.  
  611. #ifdef C_ANSI
  612. SHORT APIENTRY
  613. WflJobSelect(TNODE_P pstWorkHead,
  614.              LLIST_P pstWorkList,
  615.              WORK_FLOW_PP ppstWorkNdx,
  616.              WORK_ITEM_PP ppstWorkItem,
  617.              PVOID   * ppvData)
  618. #else
  619. SHORT APIENTRY
  620. WflJobSelect(pstWorkHead,pstWorkList,ppstWorkNdx,ppstWorkItem,ppvData)
  621. TNODE_P  pstWorkHead;      /* main set of WORK_ITEM data */
  622. LLIST_P  pstWorkList;     /* this process WORK_FLOW list */
  623. WORK_FLOW_PP ppstWorkNdx;  /* this process WORK_FLOW which was selected */
  624. WORK_ITEM_PP ppstWorkItem;  /* this is the work item selected */
  625. PVOID   * ppvData;        /* ptr to return data if found */
  626. #endif
  627. {
  628.    C_DEF_MODULE("WflJobSelect")
  629.  
  630.    LLIST_P  pstList;
  631.    LLIST_P  pstWorkLst;
  632.    WORK_FLOW_P  pstWorkFlow;
  633.    WORK_ITEM_P pstWorkItem;
  634.    TNODE_P   pstNode;
  635.  
  636.    BOOL     fFoundJob = C_FALSE;
  637.  
  638.    *ppvData = NULL;
  639.  
  640.    /*
  641.    **  Check all jobs based on jobs which this process can process
  642.    */
  643.  
  644.    pstList = pstWorkList;
  645.  
  646.    while(pstList != NULL && !fFoundJob)
  647.    {
  648.        pstWorkFlow = (WORK_FLOW_P) pstList -> pvData;
  649.  
  650.        C_STATUS = MemTreFindNode(pstWorkHead,
  651.                                  (PVOID) &pstWorkFlow -> sTrnState[WFL_SEL_STATE],
  652.                                  CompareState,
  653.                                  &pstNode);
  654.  
  655.        if(pstNode != NULL && !fFoundJob)
  656.        {
  657.           /*
  658.           **  Found 1 or more jobs at this state
  659.  
  660.           **
  661.           **  Check each member in linked list till no more or got one
  662.           */
  663.  
  664.           pstWorkLst = (LLIST_P) pstNode -> pvData;
  665.  
  666.           while(pstWorkLst != NULL && !fFoundJob)
  667.           {
  668.              pstWorkItem = (WORK_ITEM_P) pstWorkLst -> pvData;
  669.  
  670.              if(!pstWorkItem -> fLocked)
  671.              {
  672.  
  673.                 /*
  674.                 **  Mark job as locked, we are new owners
  675.                 */
  676.  
  677.                 *ppstWorkItem = pstWorkItem;
  678.  
  679.                 *ppstWorkNdx = pstWorkFlow;
  680.  
  681.                 pstWorkItem -> fLocked = C_TRUE;
  682.  
  683.                 strcpy(pstWorkItem -> szKey, pstWorkFlow -> szKey);
  684.  
  685.                 *ppvData = pstWorkItem -> pvData;
  686.  
  687.                 fFoundJob = C_TRUE;
  688.  
  689.              }
  690.  
  691.              pstWorkLst = pstWorkLst -> psNext;
  692.           }
  693.  
  694.        }   
  695.  
  696.        pstList = pstList -> psNext;
  697.  
  698.  
  699.    }
  700.  
  701.  
  702.  
  703.    if(!fFoundJob)
  704.       C_SET_STATUS(WFL_NO_JOB)
  705.  
  706.    C_RETURN
  707.  
  708. }
  709.  
  710.  
  711.  
  712. /*
  713. **  WflJobTrans
  714. ** 
  715. **  Set the job to the appropriate transition state
  716. **  and unlocks job if told to
  717. */ 
  718.  
  719. #ifdef C_ANSI
  720. SHORT APIENTRY
  721. WflJobTrans(TNODE_PP ppstWorkTree,
  722.             WORK_ITEM_P pstWorkItem,
  723.             WORK_FLOW_P pstWorkFlow,
  724.             SHORT  sTrn,
  725.             BOOL   fUnlock)
  726. #else
  727. SHORT APIENTRY
  728. WflJobTrans(ppstWorkTree,pstWorkItem,pstWorkFlow,sTrn,fUnlock)
  729. TNODE_PP ppstWorkTree;
  730. WORK_ITEM_P pstWorkItem;
  731. WORK_FLOW_P pstWorkFlow;
  732. SHORT  sTrn;
  733. BOOL   fUnlock;
  734. #endif
  735. {
  736.    C_DEF_MODULE("WflJobTrans")
  737.  
  738.    SHORT  sSaveState;
  739.    WORK_ITEM_P  pstTempWorkItem;
  740.    BOOL   fFoundJob = C_FALSE;
  741.    TNODE_P  pstWorkTree;
  742.    TNODE_P  pstNode;
  743.    LLIST_P  pstWorkLst;
  744.    LLIST_P  pstHeadLst;
  745.  
  746. #if TEST
  747.    printf("WflJobTrans: Setting %s to state %d\n",
  748.            pstWorkItem -> szId,
  749.            pstWorkFlow -> sTrnState[sTrn]);
  750. #endif
  751.  
  752.    pstWorkTree = *ppstWorkTree;
  753.  
  754.    sSaveState = pstWorkItem -> sState;
  755.  
  756.    if(fUnlock)
  757.       pstWorkItem -> fLocked = C_FALSE;
  758.  
  759.    /*
  760.    **  Must also unlink from link list in workflow tree
  761.    **  and add to new link list
  762.    */
  763.  
  764.    C_STATUS = MemTreFindNode(pstWorkTree,
  765.  
  766.                              (PVOID) &sSaveState,
  767.                              CompareState,
  768.                              &pstNode);
  769.  
  770.    if(
  771.       (pstNode != NULL) &&
  772.       (!fFoundJob)
  773.      )
  774.    {  
  775.  
  776.       /*
  777.       **  Found 1 or more jobs at this state
  778.       **
  779.       **  Check each member in linked list till no more or got one
  780.       */
  781.  
  782.       pstWorkLst = (LLIST_P) pstNode -> pvData;
  783.  
  784.       pstHeadLst = pstWorkLst;
  785.  
  786.       /*
  787.       **  Follow link list, scan all jobs at this state
  788.       */
  789.  
  790.       while(
  791.             (pstWorkLst != NULL) &&
  792.             (!fFoundJob)
  793.            )
  794.       {
  795.  
  796.          pstTempWorkItem = (WORK_ITEM_P) pstWorkLst -> pvData;
  797.  
  798.          /*
  799.          **  All same states, check if match on owner
  800.          */
  801.  
  802.          if(strcmp(pstWorkItem -> szKey,pstTempWorkItem -> szKey) == 0)
  803.          {
  804.  
  805.              /*
  806.              **  Found it, delete from old list, add to new/current one
  807.  
  808.              */
  809.  
  810.              fFoundJob = C_TRUE;
  811.  
  812.              C_STATUS = MemLstDeleteMember(pstHeadLst,
  813.                                            pstWorkLst,
  814.                                            &pstHeadLst);
  815.  
  816.              if(pstHeadLst == NULL)
  817.              {
  818.  
  819.                 /*
  820.                 **  Delete tree entry because no more at this state
  821.                 */
  822.  
  823.                 C_STATUS = MemTreDeleteNode(pstWorkTree,
  824.                                             (PVOID) &sSaveState,
  825.                                             CompareState,
  826.                                             &pstWorkTree);
  827. #if TEST
  828.                 printf("WflJobTrans: Deleting state %d\n",
  829.                         sSaveState);
  830. #endif
  831.  
  832.              }
  833.              else
  834.              {   
  835. #if TEST
  836.                 printf("WflJobTrans: Resetting node for state %d\n",
  837.                         sSaveState);
  838. #endif
  839.                pstNode -> pvData = (PVOID) pstHeadLst;  /* reset */
  840.              }
  841.  
  842.              /*
  843.              **  Add to new/current list
  844.              */
  845.  
  846.              pstWorkItem -> sState = pstWorkFlow -> sTrnState[sTrn];
  847.  
  848.              C_STATUS = WflJobAdd(&pstWorkTree,pstWorkItem);
  849.  
  850.  
  851.          }
  852.  
  853.          pstWorkLst = pstWorkLst -> psNext;
  854.      }
  855.  
  856.   }
  857.  
  858.   *ppstWorkTree = pstWorkTree;
  859.  
  860.   C_RETURN
  861.  
  862. }
  863.  
  864.  
  865. /*
  866. **  CompareState       used for SHORT to node comparison of short ids
  867. **                     by search routines
  868. */
  869.  
  870. SHORT CompareState(pvData1,pvData2)
  871. PVOID pvData1;
  872. PVOID pvData2;
  873. {
  874.    PSHORT psState1;
  875.    PSHORT psState2;
  876.  
  877.    LLIST_P  pstList;
  878.  
  879.    psState1 = (PSHORT) pvData1;
  880.  
  881.    pstList = (LLIST_P) pvData2;
  882.  
  883.    psState2 = (PSHORT) pstList -> pvData;
  884.  
  885.    if(*psState1 == *psState2)
  886.       return(0);
  887.    else if(*psState1 > *psState2)
  888.       return(-1);
  889.    else
  890.       return(1);
  891.  
  892. }
  893.  
  894.  
  895.  
  896. /*
  897. **  CompareNodeState   used for node to node comparison of short ids
  898. **                     by delete routines
  899. */
  900.  
  901.  
  902. SHORT CompareNodeState(pvData1,pvData2)
  903. PVOID pvData1;
  904. PVOID pvData2;
  905. {
  906.    PSHORT psState1;
  907.    PSHORT psState2;
  908.  
  909.    LLIST_P  pstList1;
  910.    LLIST_P  pstList2;
  911.  
  912.    pstList1 = (LLIST_P) pvData1;
  913.  
  914.    psState1 = (PSHORT) pstList1 -> pvData;
  915.  
  916.    pstList2 = (LLIST_P) pvData2;
  917.  
  918.    psState2 = (PSHORT) pstList2 -> pvData;
  919.  
  920.    if(*psState1 == *psState2)
  921.       return(0);
  922.    else if(*psState1 > *psState2)
  923.       return(-1);
  924.    else
  925.       return(1);
  926.  
  927. }
  928.  
  929.  
  930.  
  931.  
  932.