CIS307: Fall 97: Homework 2: Using Unix System Services

Given September 23, due October 6 by 10pm.

We have processes STORE_MANAGER, RAND_PROC1, RAND_PROC2 created(forked) by the parent process HMW_MAIN.

These files will be compiled separately and linked together to form the image hmw2. To run the program you will then call hmw2 with as command line parameters the names of two files [for convenience in the following we assume these names are LOG.DAT and INIT.DAT].

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 the pipe RAND_BOX2. Each message as it is sent or received, it is time-stamped and logged in the file 'LOG.DAT' by the STORE_MANAGER and by the RAND_PROCi processes.

The STORE_MANAGER keeps in a TABLE TABLE_SIZE [say, 10] pairs (TABLE_ID, TABLE_ELEM). The TABLE will be a structure of the form

    struct {
      char id[TABLE_ID_SIZE+1];
      char value[TABLE_ELEM_SIZE+1];
    } TABLE;
not of the form
    struct {
      char *id;
      char *value;
    } TABLE;
where TABLE_ID_SIZE and TABLE_ELEM_SIZE are constants, say, 12 and 8. The ids kept in TABLE are read from the file 'INIT.DAT'. STORE_MANAGER will initialize the value fields in TABLE with random strings.

On the TABLE are carried out two operations, TABLE_UPDATE and TABLE_READ.

   function TABLE_UPDATE (WHO : TABLE_ID;
    			    WHAT : TABLE_ELEM) return INTEGER;
    {It updates the value of WHO to be WHAT. It returns 0 iff successful}
    {i.e. if WHO was a TABLE_ID in the table}
    {Note that WHO denotes the pair with first element equal to WHO.}

   function TABLE_READ (WHO : TABLE_ID;
    			  out WHAT  : TABLE_ELEM) return INTEGER;
    {It retrieves the value of WHO and stores it in WHAT. 
     It returns 0 iff successful, i.e. if WHO was a TABLE_ID in the table}

Here is how the STORE_MANAGER should behave:

   STORE_MANAGER:
       initialization [including opening LOG.DAT in append+write mode,
           opening and reading INIT.DAT and initializing TABLE];
       loop
	    wait for the arrival of a new request;
	    log the message and start the corresponding operation;
	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 An Origin Id [the process id of the sending process, as a
          five digit number]
	o A message code ['U' for TABLE_UPDATE, 'R' for TABLE_READ] 
	o The  operands required by the corresponding operation [hence for 
	  TABLE_UPDATE, the 'U' will be followed by a TABLE_ID value [it
	  is TABLE_ID_SIZE characters] 
	  and by a TABLE_ELEM value [it is TABLE_ELEM_SIZE characters], 
	  while for TABLE_READ, the 'R' will be followed only by TABLE_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 TABLE_ID and TABLE_ELEM].

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

   RAND_PROCi:
       initialization (including opening LOG.DAT in append+write mode,
            opening and reading INIT.DAT into a local array IDS];
       loop
	    generate a random TABLE_READ or TABLE_UPDATE request;
	    [in both operations the TABLE_ID should be selected 
	     at random from IDS; in the TABLE_UPDATE operation 
             TABLE_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 [say, between 0 and 2 seconds];
	end loop
        conclusion;
In writing RAND_PROCi you should represent the sending of a message and the receiving of the corresponding response as taking place within calls to the following functions:
   function TABLE_UPDATE (WHO : TABLE_ID;
    			   WHAT  : TABLE_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 TABLE_READ (WHO : TABLE_ID;
    			  var WHAT  : TABLE_ELEM) return INTEGER;
    {It retrieves the value of WHO and stores it in WHAT. 
     It returns 0 iff successful}
I have used the same name and form for the functions used in STORE_MANAGER to access TABLE, and in processes RAND_PROC1 and RAND_PROC2 to communicate with STORE_MANAGER. I did it intentionally to stress that through communication the TABLE is as if it were local to its users. [The fact that you are using the same name should not give origin to problems because they occur in different files and should be made local to those files.]

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:
       pid_t pids[3];
       initialization;
       if ((pids[0]=fork())<0){perror("Error forking STORE_MANAGER ");exit(1);}
       else if (pids[0]==0) STORE_MANAGER();
       if ((pids[1]=fork())<0) {perror("Error forking RAND_PROC1"); exit(1);}
       else if (pids[1]==0) RAND_PROC1();
       if ((pids[2]=fork())<0) {perror("Error forking RAND_PROC2"); exit(1);}
       else if (pids[2]==0) RAND_PROC2();
       loop
	   Prompt the User;
	   If the answer is "1" then
		send a signal to RAND_PROC1 [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, including closing LOG.DAT;
RAND_PROC1 and RAND_PROC2 should respond within callbacks to the signals from HMW_MAIN.

The INIT.DAT file is:

  NETSCAPE
     LASMO
     INTEL
     HONDA
 MICROSOFT
    DISNEY
   CHEVRON
   BORDERS
    FINOVA
  HALLWOOD

ingargiola@cis.temple.edu