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, respectively, 9 [STORE_ID_SIZE] and 12 [STORE_ELEM_SIZE] characters. STORE_ID represents a social security number [for example "155243352"] and STORE_ELEM represents the corresponding balance [for example " 4563.75"]. 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}
{i.e. if WHO was a STORE_ID in the store}
{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,i.e. if WHO was a STORE_ID in the store}
Here is an important complication: STORE_READ and STORE_UPDATE
are slow operations [assume that they involve IO], taking one second.
During this time the STORE_MANAGER should be able to work on requests
involving other STORE_IDs.
To deal with this problem we assume that operations are
executed each as two operations. For STORE_READ, STORE_READ_INIT and
STORE_READ_END, and for STORE_UPDATE,
STORE_UPDATE_INIT and STORE_UPDATE_END.
You decide what should be the parameters to use for these operations.
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}
I have used the same name and form for the functions used in
STORE_MANAGER to access STORE, and in 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:
pid_t pids[3];
initialization;
if ((pids[0]=fork())<0) {perror("fork"); exit(1);}
else if (pids[0]==0) STORE_MANAGER();
if ((pids[1]=fork())<0) {perror("fork"); exit(1);}
else if (pids[1]==0) RAND_PROC1();
if ((pids[2]=fork())<0) {perror("fork"); 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;
RAND_PROC1 and RAND_PROC2 should respond within callbacks to the
signals from HMW_MAIN.
ingargiola@cis.temple.edu