home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- *+
- ** Module Name: WFL.C
- **
- ** Description: Workflow extensions to
- ** MOS:
- **
- ** Multi-tasking
- ** Operating
- ** System
- ** Simulation
- **
- **
- ** Written by: John Tal
- **
- **
- **
- ** Modification History:
- **
- ** Date Programmer Mod# Modification
- ** ---------------------------------------------------------------------------
- ** 04-JUL-1991 J. Tal V1.0-000 New
- **
- *-
- */
-
-
- #ifdef C_ANSI
- #include <string.h>
- #include <stdlib.h>
- #include <stdio.h>
- #endif
-
-
- #include <memlib.h>
- #include <time.h>
-
-
- #include <mos.h>
-
- #include <wfl.h>
-
-
- /*
- ** Workflow Variables
- */
-
- #ifdef TEST
- #ifdef C_ANSI
- SHORT ProcEndMain(PROC_P pstProc);
- VOID ProcEndInit(VOID);
- VOID ProcProcMain(PROC_P pstProc);
- VOID ProcProcInit(VOID);
- VOID ProcLoadMain(PROC_P pstProc);
- VOID ProcLoadInit(VOID);
- #else
- SHORT ProcEndMain();
- VOID ProcEndInit();
- VOID ProcProcMain();
- VOID ProcProcInit();
- VOID ProcLoadMain();
- VOID ProcLoadInit();
- #endif
- #endif
-
-
-
- #ifdef TEST
-
- struct JOB_S /* a dummy 'job' to process */
- {
- CHAR szTitle[32];
- CHAR szStatus[32];
- };
-
- typedef struct JOB_S JOB_T;
- typedef JOB_T * JOB_P;
-
-
- JOB_T stJob1; /* some jobs */
- JOB_T stJob2;
- JOB_T stJob3;
- JOB_T stJob4;
-
- #endif
-
-
- TNODE_P pstWorkTree = NULL; /* the job tree */
-
- WORK_FLOW_T stLoadProc;
- WORK_FLOW_T stProcProc;
- WORK_FLOW_T stEndProc;
-
- LLIST_P pstLoadProfile = NULL; /* LIST of workflow for each process */
- LLIST_P pstProcProfile = NULL;
- LLIST_P pstEndProfile = NULL;
-
- LONG glJobCount = 0;
-
- WORK_ITEM_T stWorkItem1; /* data to be processed */
- WORK_ITEM_T stWorkItem2;
- WORK_ITEM_T stWorkItem3;
- WORK_ITEM_T stWorkItem4;
-
- #define WFL_STD_SLEEP_SECS 3
-
-
-
- /* ******************************************************************** */
- /* *********** TEST CODE ********************************************** */
- /* ******************************************************************** */
-
- /*
- ** Wfl Main
- */
-
- #ifdef TEST
-
- main()
- {
- C_DEF_MODULE("WflMain")
-
- C_STATUS = MosInit();
-
- /*
- ** Initialize each job
- */
-
- stWorkItem1.sState = 100;
- strcpy(stWorkItem1.szId,"Job1");
- strcpy(stWorkItem1.szKey,"No Owner");
- stWorkItem1.fLocked = C_FALSE;
- stWorkItem1.pvData = (PVOID) &stJob1;
-
-
- stWorkItem2.sState = 100;
- strcpy(stWorkItem2.szId,"Job2");
- strcpy(stWorkItem2.szKey,"No Owner");
- stWorkItem2.fLocked = C_FALSE;
- stWorkItem2.pvData = (PVOID) &stJob2;
-
-
- stWorkItem3.sState = 100;
- strcpy(stWorkItem3.szId,"Job3");
- strcpy(stWorkItem3.szKey,"No Owner");
- stWorkItem3.fLocked = C_FALSE;
- stWorkItem3.pvData = (PVOID) &stJob3;
-
-
- stWorkItem4.sState = 100;
- strcpy(stWorkItem4.szId,"Job4");
- strcpy(stWorkItem4.szKey,"No Owner");
- stWorkItem4.fLocked = C_FALSE;
- stWorkItem4.pvData = (PVOID) &stJob4;
-
- /*
- ** Add each job to master list in tree
- */
-
- WflJobAdd(&pstWorkTree,&stWorkItem1);
- WflJobAdd(&pstWorkTree,&stWorkItem2);
- WflJobAdd(&pstWorkTree,&stWorkItem3);
- WflJobAdd(&pstWorkTree,&stWorkItem4);
-
-
- /*
- ** Load up some processes, all use the MosGenericProc as their
- ** code. This could be modified for experimentation to
- ** be other processes modeled after MosGenericProc but
- ** with specialized functions
- */
-
- ProcLoadInit();
- ProcProcInit();
- ProcEndInit();
-
- C_STATUS = MosProcCreate(ProcLoadMain,"PROC_LOAD",10);
- C_STATUS = MosProcCreate(ProcProcMain,"PROC_PROC",10);
- C_STATUS = MosProcCreate(ProcEndMain,"PROC_END",10);
-
-
- C_STATUS = MosScheduler();
-
- C_RETURN
- }
-
-
- /* ******************************************************************** */
- /* ******************************************************************** */
- /* ******************************************************************** */
-
-
-
- #ifdef C_ANSI
- VOID
- ProcLoadInit(VOID)
- #else
- VOID
- ProcLoadInit()
- #endif
- {
- strcpy(stLoadProc.szKey,"LOAD_PROC");
- stLoadProc.sTrnStates = 4;
- stLoadProc.sTrnState[WFL_SEL_STATE] = 100; /* Selection */
- stLoadProc.sTrnState[WFL_ACT_STATE] = 101; /* Activation */
- stLoadProc.sTrnState[WFL_TRN_STATE + 0] = 200; /* successful completion */
- stLoadProc.sTrnState[WFL_TRN_STATE + 1] = 900; /* error */
-
- WflProAdd(&pstLoadProfile,&stLoadProc);
-
- }
-
-
- #ifdef C_ANSI
- VOID
- ProcLoadMain(PROC_P pstProc)
- #else
- VOID
- ProcLoadMain(pstProc)
- PROC_P pstProc;
- #endif
- {
- C_DEF_MODULE("ProcLoadMain")
-
- WORK_FLOW_P pstWorkNdx;
- WORK_ITEM_P pstWorkItem;
- JOB_P pstJob;
-
- static SHORT sTrys = 0;
-
-
- C_STATUS = WflJobSelect(pstWorkTree,
- pstLoadProfile,
- &pstWorkNdx,
- &pstWorkItem,
- (PVOID *) &pstJob);
-
- if(!C_STATUS)
- {
-
- WflJobTrans(&pstWorkTree,
- pstWorkItem,
- pstWorkNdx,
- WFL_ACT_STATE,
- C_FALSE); /* mark in process */
-
- sprintf(pstJob -> szTitle,"Job %d Loaded at %d\n",
- glJobCount,
- MosCurTime());
-
- glJobCount++;
-
-
- WflJobTrans(&pstWorkTree,
- pstWorkItem,
- pstWorkNdx,
- WFL_TRN_STATE+WFL_TRN_OK,C_TRUE); /* mark ok */
-
- C_STATUS = MosReschedReady(pstProc);
-
- }
- else
- {
- sTrys++;
- if(sTrys > 2)
- {
- C_STATUS = MosProcTerm(pstProc);
- C_LEAVE(C_OK);
- }
- pstProc -> lWakeTime = MosCurTime() + WFL_STD_SLEEP_SECS;
- C_STATUS = MosSleep(pstProc);
- }
-
- C_MODULE_EXIT:
-
- ;
-
- }
-
-
- #ifdef C_ANSI
- VOID
- ProcProcInit(VOID)
- #else
- VOID
- ProcProcInit()
- #endif
- {
- strcpy(stProcProc.szKey,"PROC_PROC");
- stProcProc.sTrnStates = 4;
- stProcProc.sTrnState[0] = 200; /* Selection */
- stProcProc.sTrnState[1] = 201; /* Activation */
- stProcProc.sTrnState[2] = 300; /* successful completion */
- stProcProc.sTrnState[4] = 901; /* error */
-
- WflProAdd(&pstProcProfile,&stProcProc);
- }
-
-
- #ifdef C_ANSI
- VOID
- ProcProcMain(PROC_P pstProc)
- #else
- VOID
- ProcProcMain(pstProc)
- PROC_P pstProc;
- #endif
- {
- C_DEF_MODULE("ProcProcMain")
-
- WORK_FLOW_P pstWorkNdx;
- WORK_ITEM_P pstWorkItem;
- JOB_P pstJob;
-
- static SHORT sTrys = 0;
-
-
- C_STATUS = WflJobSelect(pstWorkTree,
- pstProcProfile,
- &pstWorkNdx,
- &pstWorkItem,
- (PVOID *) &pstJob);
- if(!C_STATUS)
- {
-
- WflJobTrans(&pstWorkTree,
- pstWorkItem,
- pstWorkNdx,
- WFL_ACT_STATE,
- C_FALSE); /* mark in process */
-
- sprintf(pstJob -> szStatus,"Job Processed at %d\n",
- MosCurTime());
-
-
- WflJobTrans(&pstWorkTree,
- pstWorkItem,
- pstWorkNdx,
- WFL_TRN_STATE+WFL_TRN_OK,C_TRUE); /* mark ok */
-
- C_STATUS = MosReschedReady(pstProc);
- }
- else
- {
- sTrys++;
- if(sTrys > 2)
- {
- C_STATUS = MosProcTerm(pstProc);
- C_LEAVE(C_OK);
- }
- pstProc -> lWakeTime = MosCurTime() + WFL_STD_SLEEP_SECS;
- C_STATUS = MosSleep(pstProc);
- }
-
- C_MODULE_EXIT:
-
- ;
- }
-
-
- #ifdef C_ANSI
- VOID
- ProcEndInit(VOID)
- #else
- VOID
- ProcEndInit()
- #endif
- {
- strcpy(stEndProc.szKey,"END_PROC");
- stEndProc.sTrnStates = 4;
- stEndProc.sTrnState[0] = 300; /* Selection */
- stEndProc.sTrnState[1] = 301; /* Activation */
- stEndProc.sTrnState[2] = 400; /* successful completion */
- stEndProc.sTrnState[4] = 902; /* error */
-
- WflProAdd(&pstEndProfile,&stEndProc);
-
- }
-
-
- #ifdef C_ANSI
- SHORT
- ProcEndMain(PROC_P pstProc)
- #else
- SHORT
- ProcEndMain(pstProc)
- PROC_P pstProc;
- #endif
- {
- C_DEF_MODULE("EndProcMain")
-
- WORK_FLOW_P pstWorkNdx;
- WORK_ITEM_P pstWorkItem;
- JOB_P pstJob;
- static SHORT sTrys = 0;
-
-
-
-
- C_STATUS = WflJobSelect(pstWorkTree,
- pstEndProfile,
- &pstWorkNdx,
- &pstWorkItem,
- (PVOID *) &pstJob);
-
- if(!C_STATUS)
- {
- WflJobTrans(&pstWorkTree,
- pstWorkItem,
- pstWorkNdx,
- WFL_ACT_STATE,
- C_FALSE); /* mark in process */
-
- printf("%s Ended at %d\n", pstJob -> szTitle, MosCurTime());
-
-
- WflJobTrans(&pstWorkTree,
- pstWorkItem,
- pstWorkNdx,
- WFL_TRN_STATE+WFL_TRN_OK,C_TRUE); /* mark ok */
-
- C_STATUS = MosReschedReady(pstProc);
- }
- else
- {
- sTrys++;
- if(sTrys > 2)
- {
- C_STATUS = MosProcTerm(pstProc);
- C_LEAVE(C_OK);
- }
-
- pstProc -> lWakeTime = MosCurTime() + WFL_STD_SLEEP_SECS;
- C_STATUS = MosSleep(pstProc);
-
- /* glSleepings++; */ /* must have some way to know when to shutdown */
- }
-
- C_MODULE_EXIT:
-
- ;
-
- C_RETURN
-
- }
-
-
- #endif
-
- /* end of testing code */
-
-
- /* ******************************************************************** */
- /* *********** WFL FUNCTIONS ****************************************** */
- /* ******************************************************************** */
-
- /*
- ** WflProAdd
- **
- ** Adds a profile for a process to the process' profile list
- */
-
- #ifdef C_ANSI
- SHORT APIENTRY
- WflProAdd(LLIST_PP ppstProfile, WORK_FLOW_P pstWorkFlow)
- #else
- SHORT APIENTRY
- WflProAdd(ppstProfile,pstWorkFlow)
- LLIST_PP ppstProfile;
- WORK_FLOW_P pstWorkFlow;
- #endif
- {
- C_DEF_MODULE("WflProAdd")
-
- LLIST_P pstProfile;
- LLIST_P pstList;
- LLIST_P pstTail;
-
- pstProfile = *ppstProfile;
-
- C_STATUS = MemLstAllocMember(&pstList);
-
- pstList -> pvData = (PVOID) pstWorkFlow;
-
- if(pstProfile != NULL)
- {
-
- C_STATUS = MemLstFindTailMember(pstProfile,&pstTail);
-
- C_STATUS = MemLstAddAfterMember(pstTail,pstList);
- }
- else
- pstProfile = pstList;
-
-
- *ppstProfile = pstProfile;
-
- C_RETURN
-
- }
-
-
-
- /*
- ** Add another job.
- ** Each workflow_T is in a linked-list off of a single binary tree node
- */
-
- #ifdef C_ANSI
- SHORT APIENTRY
- WflJobAdd(TNODE_PP ppstWorkTree,WORK_ITEM_P pstWorkItem)
- #else
- SHORT APIENTRY
- WflJobAdd(ppstWorkTree,pstWorkItem)
- TNODE_PP ppstWorkTree;
- WORK_ITEM_P pstWorkItem;
- #endif
- {
- C_DEF_MODULE("WflJobAdd")
-
- TNODE_P pstWorkTree;
- TNODE_P pstNode;
- LLIST_P pstList;
- LLIST_P pstNewList;
- LLIST_P pstLastList;
-
-
- pstWorkTree = *ppstWorkTree;
-
- C_STATUS = MemTreFindNode(pstWorkTree,
- (PVOID) &pstWorkItem -> sState,
- CompareState,
- &pstNode);
-
- if(pstNode == NULL)
- {
-
- #if TEST
- printf("WflJobAdd: Adding entry for state %d\n",
- pstWorkItem -> sState);
- #endif
-
- /*
- ** Must add entry for this state
- */
-
- C_STATUS = MemTreAllocNode(&pstNode);
-
- C_STATUS = MemLstAllocMember(&pstList);
-
- pstList -> pvData = (PVOID) pstWorkItem;
-
-
-
- pstNode -> pvData = (PVOID) pstList;
-
- C_STATUS = MemTreInsertNode(pstWorkTree,
- pstNode,
- CompareNodeState,
- &pstWorkTree);
-
- }
- else
- {
- #if TEST
- printf("WflJobAdd: Appending entry for state %d\n",
- pstWorkItem -> sState);
- #endif
-
- /*
- ** Find current llist
- */
-
- pstList = (LLIST_P) pstNode -> pvData;
-
- /*
- ** Make new member
- */
-
- C_STATUS = MemLstAllocMember(&pstNewList);
-
- pstNewList -> pvData = (PVOID) pstWorkItem;
-
- /*
- ** Find last one of current list
- */
-
- C_STATUS = MemLstFindTailMember(pstList,&pstLastList);
-
- /*
- ** Add new one after current last one
- ** Maintains FIFO ordering
- */
-
- C_STATUS = MemLstAddAfterMember(pstLastList,pstNewList);
-
- }
-
- *ppstWorkTree = pstWorkTree;
-
- C_RETURN
- }
-
-
-
-
- /*
- ** WflJobSelect, select a job to work on
- */
-
- #ifdef C_ANSI
- SHORT APIENTRY
- WflJobSelect(TNODE_P pstWorkHead,
- LLIST_P pstWorkList,
- WORK_FLOW_PP ppstWorkNdx,
- WORK_ITEM_PP ppstWorkItem,
- PVOID * ppvData)
- #else
- SHORT APIENTRY
- WflJobSelect(pstWorkHead,pstWorkList,ppstWorkNdx,ppstWorkItem,ppvData)
- TNODE_P pstWorkHead; /* main set of WORK_ITEM data */
- LLIST_P pstWorkList; /* this process WORK_FLOW list */
- WORK_FLOW_PP ppstWorkNdx; /* this process WORK_FLOW which was selected */
- WORK_ITEM_PP ppstWorkItem; /* this is the work item selected */
- PVOID * ppvData; /* ptr to return data if found */
- #endif
- {
- C_DEF_MODULE("WflJobSelect")
-
- LLIST_P pstList;
- LLIST_P pstWorkLst;
- WORK_FLOW_P pstWorkFlow;
- WORK_ITEM_P pstWorkItem;
- TNODE_P pstNode;
-
- BOOL fFoundJob = C_FALSE;
-
- *ppvData = NULL;
-
- /*
- ** Check all jobs based on jobs which this process can process
- */
-
- pstList = pstWorkList;
-
- while(pstList != NULL && !fFoundJob)
- {
- pstWorkFlow = (WORK_FLOW_P) pstList -> pvData;
-
- C_STATUS = MemTreFindNode(pstWorkHead,
- (PVOID) &pstWorkFlow -> sTrnState[WFL_SEL_STATE],
- CompareState,
- &pstNode);
-
- if(pstNode != NULL && !fFoundJob)
- {
- /*
- ** Found 1 or more jobs at this state
-
- **
- ** Check each member in linked list till no more or got one
- */
-
- pstWorkLst = (LLIST_P) pstNode -> pvData;
-
- while(pstWorkLst != NULL && !fFoundJob)
- {
- pstWorkItem = (WORK_ITEM_P) pstWorkLst -> pvData;
-
- if(!pstWorkItem -> fLocked)
- {
-
- /*
- ** Mark job as locked, we are new owners
- */
-
- *ppstWorkItem = pstWorkItem;
-
- *ppstWorkNdx = pstWorkFlow;
-
- pstWorkItem -> fLocked = C_TRUE;
-
- strcpy(pstWorkItem -> szKey, pstWorkFlow -> szKey);
-
- *ppvData = pstWorkItem -> pvData;
-
- fFoundJob = C_TRUE;
-
- }
-
- pstWorkLst = pstWorkLst -> psNext;
- }
-
- }
-
- pstList = pstList -> psNext;
-
-
- }
-
-
-
- if(!fFoundJob)
- C_SET_STATUS(WFL_NO_JOB)
-
- C_RETURN
-
- }
-
-
-
- /*
- ** WflJobTrans
- **
- ** Set the job to the appropriate transition state
- ** and unlocks job if told to
- */
-
- #ifdef C_ANSI
- SHORT APIENTRY
- WflJobTrans(TNODE_PP ppstWorkTree,
- WORK_ITEM_P pstWorkItem,
- WORK_FLOW_P pstWorkFlow,
- SHORT sTrn,
- BOOL fUnlock)
- #else
- SHORT APIENTRY
- WflJobTrans(ppstWorkTree,pstWorkItem,pstWorkFlow,sTrn,fUnlock)
- TNODE_PP ppstWorkTree;
- WORK_ITEM_P pstWorkItem;
- WORK_FLOW_P pstWorkFlow;
- SHORT sTrn;
- BOOL fUnlock;
- #endif
- {
- C_DEF_MODULE("WflJobTrans")
-
- SHORT sSaveState;
- WORK_ITEM_P pstTempWorkItem;
- BOOL fFoundJob = C_FALSE;
- TNODE_P pstWorkTree;
- TNODE_P pstNode;
- LLIST_P pstWorkLst;
- LLIST_P pstHeadLst;
-
- #if TEST
- printf("WflJobTrans: Setting %s to state %d\n",
- pstWorkItem -> szId,
- pstWorkFlow -> sTrnState[sTrn]);
- #endif
-
- pstWorkTree = *ppstWorkTree;
-
- sSaveState = pstWorkItem -> sState;
-
- if(fUnlock)
- pstWorkItem -> fLocked = C_FALSE;
-
- /*
- ** Must also unlink from link list in workflow tree
- ** and add to new link list
- */
-
- C_STATUS = MemTreFindNode(pstWorkTree,
-
- (PVOID) &sSaveState,
- CompareState,
- &pstNode);
-
- if(
- (pstNode != NULL) &&
- (!fFoundJob)
- )
- {
-
- /*
- ** Found 1 or more jobs at this state
- **
- ** Check each member in linked list till no more or got one
- */
-
- pstWorkLst = (LLIST_P) pstNode -> pvData;
-
- pstHeadLst = pstWorkLst;
-
- /*
- ** Follow link list, scan all jobs at this state
- */
-
- while(
- (pstWorkLst != NULL) &&
- (!fFoundJob)
- )
- {
-
- pstTempWorkItem = (WORK_ITEM_P) pstWorkLst -> pvData;
-
- /*
- ** All same states, check if match on owner
- */
-
- if(strcmp(pstWorkItem -> szKey,pstTempWorkItem -> szKey) == 0)
- {
-
- /*
- ** Found it, delete from old list, add to new/current one
-
- */
-
- fFoundJob = C_TRUE;
-
- C_STATUS = MemLstDeleteMember(pstHeadLst,
- pstWorkLst,
- &pstHeadLst);
-
- if(pstHeadLst == NULL)
- {
-
- /*
- ** Delete tree entry because no more at this state
- */
-
- C_STATUS = MemTreDeleteNode(pstWorkTree,
- (PVOID) &sSaveState,
- CompareState,
- &pstWorkTree);
- #if TEST
- printf("WflJobTrans: Deleting state %d\n",
- sSaveState);
- #endif
-
- }
- else
- {
- #if TEST
- printf("WflJobTrans: Resetting node for state %d\n",
- sSaveState);
- #endif
- pstNode -> pvData = (PVOID) pstHeadLst; /* reset */
- }
-
- /*
- ** Add to new/current list
- */
-
- pstWorkItem -> sState = pstWorkFlow -> sTrnState[sTrn];
-
- C_STATUS = WflJobAdd(&pstWorkTree,pstWorkItem);
-
-
- }
-
- pstWorkLst = pstWorkLst -> psNext;
- }
-
- }
-
- *ppstWorkTree = pstWorkTree;
-
- C_RETURN
-
- }
-
-
- /*
- ** CompareState used for SHORT to node comparison of short ids
- ** by search routines
- */
-
- SHORT CompareState(pvData1,pvData2)
- PVOID pvData1;
- PVOID pvData2;
- {
- PSHORT psState1;
- PSHORT psState2;
-
- LLIST_P pstList;
-
- psState1 = (PSHORT) pvData1;
-
- pstList = (LLIST_P) pvData2;
-
- psState2 = (PSHORT) pstList -> pvData;
-
- if(*psState1 == *psState2)
- return(0);
- else if(*psState1 > *psState2)
- return(-1);
- else
- return(1);
-
- }
-
-
-
- /*
- ** CompareNodeState used for node to node comparison of short ids
- ** by delete routines
- */
-
-
- SHORT CompareNodeState(pvData1,pvData2)
- PVOID pvData1;
- PVOID pvData2;
- {
- PSHORT psState1;
- PSHORT psState2;
-
- LLIST_P pstList1;
- LLIST_P pstList2;
-
- pstList1 = (LLIST_P) pvData1;
-
- psState1 = (PSHORT) pstList1 -> pvData;
-
- pstList2 = (LLIST_P) pvData2;
-
- psState2 = (PSHORT) pstList2 -> pvData;
-
- if(*psState1 == *psState2)
- return(0);
- else if(*psState1 > *psState2)
- return(-1);
- else
- return(1);
-
- }
-
-
-
-