Homework 3: Using Unix System Services

This homework (Hints) is given October 24 and is due November 6 by 5pm.

We have three processes: STORE_MANAGER, RAND_PROC1, and RAND_PROC2. These processes are created by the parent process HMW_MAIN.

STORE_MANAGER receives messages from RAND_PROC1 and RAND_PROC2 through the pipe C_BOX. It responds to messages from RAND_PROC1 by placing the responses in the pipe RAND_BOX1. It responds to messages from RAND_PROC2 by placing the responses in RAND_BOX2. Each message is time-stamped and logged in the file 'LOG.DAT' by the STORE_MANAGER. Each message is also time-stamped and logged in the file 'CHILDprocid.DAT' by RAND_PROCi.

The STORE_MANAGER keeps in a STORE at least 10 [STORE_SIZE] pairs (STORE_ID, STORE_ELEM); you choose an initial list of pairs. STORE_ID and STORE_ELEM are strings of up to, respectively, 14 [STORE_ID_SIZE] and 8 [STORE_ELEM_SIZE] characters. STORE_ID represents the name of a stock, say, "ibm", "microsoft", etc. and STORE_ELEM represents the corresponding stock value, as a string. The STORE carries out two operations STORE_UPDATE and STORE_READ.

   function STORE_UPDATE (WHO : STORE_ID;
    			   WHAT  : STORE_ELEM) return INTEGER;
    {It updates the value of WHO to be WHAT. It returns 0 iff successful}
    {Note that WHO denotes the pair with first element equal to WHO.}

   function STORE_READ (WHO : STORE_ID;
    			  var WHAT  : STORE_ELEM) return INTEGER;
    {It retrieves the value of WHO and stores it in WHAT. 
     It returns 0 iff successful}

Here is an important complication: STORE_READ and STORE_UPDATE are slow operations [imagine that they involve IO], taking one second, during which time the STORE_MANAGER should be able to work on requests involving other STORE_IDs. Thus we assume that operations are executed in two phases STORE_READ_INIT and STORE_READ_END, and STORE_UPDATE_INIT and STORE_UPDATE_END. You decide on the parameters to use in each phase.

Here is how the STORE_MANAGER should behave:

   STORE_MANAGER:
       initialization;
       loop
	    wait for the completion of an operation or the arrival
	    of a new request;
            if it is a new request then
	       log the message and start the corresponding operation;
            else if it is a completion then
	       complete the operation, send the response, and log it;
	end loop
        conclusion;

STORE_MANAGER receives messages that consist of, in sequence:

	o An Origin Code ['1' for RAND_PROC1, '2' for RAND_PROC2]
	o A message code ['U' for STORE_UPDATE, 'G' for STORE_READ] 
	o The  operands required by the corresponding operation [hence for 
	  STORE_UPDATE, the 'U' will be followed by a STORE_ID value [it
	  is STORE_ID_SIZE characters] 
	  and by a STORE_ELEM value [it is STORE_ELEM_SIZE characters], 
	  while for STORE_READ, the 'G' will be followed only by STORE_ID.] 

The STORE_MANAGER responses consist of the character representing the operation requested, followed by the result of the operation ['0' for success, '1' for failure], followed by the values involved in the operation [both STORE_ID and STORE_ELEM].

RAND_PROC1 and RAND_PROC2 have the same form [but use different seeds for the random number generator]:

   RAND_PROCi:
       initialization;
       loop
	    generate a random STORE_READ or STORE_UPDATE request;
	    [in both operations the STORE_ID should be selected 
	     at random from a list maintained at RAND_PROCi; in the 
             STORE_UPDATE operation STORE_ELEM should be created using 
	     a random number generator]
	    send the request and log it;
	    wait for the corresponding response and log it;
	    wait some random time;
	end loop
        conclusion;
In writing RAND_PROCi you should represent the sending of a message and the receiving of the corresponding response within calls to the following functions:
   function STORE_UPDATE (WHO : STORE_ID;
    			   WHAT  : STORE_ELEM) return INTEGER;
    {It updates the value of WHO to be WHAT. It returns 0 iff successful}
    {Note that WHO denotes the pair with first element equal to WHO.}
   function STORE_READ (WHO : STORE_ID;
    			  var WHAT  : STORE_ELEM) return INTEGER;
    {It retrieves the value of WHO and stores it in WHAT. 
     It returns 0 iff successful}
As you may have noticed, I have used the same name and form for the functions used in the STORE_MANAGER to access STORE, and in the processes RAND_PROC1 and RAND_PROC2 to communicate with STORE_MANAGER. I did it intentionally to stress that through communication the STORE is as if it were local to its users.

HMW_MAIN, after starting the other processes, in a loop prompts the users to ask if they want to see statistical information from RAND_PROC1 and RAND_PROC2.

   HMW_MAIN:
       initialization;
       fork STORE_MANAGER, RAND_PROC1, RAND_PROC2;
       loop
	   Prompt the User;
	   If the answer is "1" then
		send a signal to RAND_PROC1, and RAND_PROC1 
		will write to the screen the number of Read and 
		Update messages that it has executed [different 
		numbers represents the Reads started and completed, 
		and the Updates started and completed].
	   else if the answer is "2", then
		the same is done with RAND_PROC2
	   else 
		send signals to RAND_PROC1, RAND_PROC2 and
		STORE_MANAGER requesting that they terminate;
		wait that they all exit and exit the loop;
	end loop
        conclusion;
The interaction between HMW_MAIN and RAND_PROC1 and RAND_PROC2 for requests "1" and "2" should not interfere with the regular operations of these processes.

ingargiola@cis.temple.edu