ORIGIN '~beta/distribution/shell';
INCLUDE 'serverinterface'; (* to communicate with the server *)
INCLUDE 'clientinterface'; (* to bind shelltype to
NPSclient (because it uses notifications) *)
INCLUDE 'notification'; (* to subscribe to notifications *)
INCLUDE 'sharedpersistentstore'; (* to make use of the concurrency control mechanism *)
INCLUDE 'recordlib'; (* to store persons in a register *)
INCLUDE 'transaction'; (* to use transactions *)
--- program: descriptor ---
shellEnv
(#
shellType:: NPSclient
(# notifyImpl::(#
do theNotification.display;
#);
ps: @sharedpersistentstore
(# maxCountOnDanglerHit::<
(# do 10->value #);
#);
serverEnsembleName: ^Text;
serverEnsemble: ^ensemble;
thenotificationmanager:^notificationmanager; PSname:^text;
newreg:^register;
s:^register;
rootname:^text;
regname:^text;
do
(* Get a reference to the ensemble on which the server is running *)
(******************************************************************)
'Enter Persistens Server hostname: ' -> screen.putText;
keyboard.getLine -> serverEnsembleName[];
getHost: (ensemble##, serverEnsembleName[])
-> theShell.myEnsemble.ns.get -> serverEnsemble[];
(* open shared persistent store *)
(********************************)
'Open PS ? '-> screen.puttext;
keyboard.getline->PSname[];
open:
(# exists:@boolean;
do true->exists;
(PSname[],theShell[],serverensemble[])->PS.open
(# notfound::<(# do false->exists;
'The store is created ...'->puttext;
PSname[]->PS.create;
leave open;
#);
#);
(if not exists then 'done'->putline if);
#);
(* subscribe to UPDATE and WAITFORLOCK notifications *)
(*****************************************************)
getnotificationmanager:(NotificationManager##, 'Notificationmanager')
-> serverEnsemble.ns.get -> thenotificationmanager[];
(if (thenotificationmanager[] <> NONE) then
subscribe: (# thesubscription: ^subscription;
do
&subscription[]->thesubscription[];
(theShell[],'all',PSname[],Update)
->subscribetoPSEvent->theSubscription[];
theSubscription[]
->thenotificationmanager.subscribeNotification;
(theShell[],'all',PSname[],Waitforlock)
->subscribetoPSEvent->theSubscription[];
theSubscription[]
->thenotificationmanager.subscribeNotification;
#);
if);
(* start transaction loop *)
(**************************)
transactionloop:
(# lmode:@integer;
lpolicy:@integer;
do
'Access the ps for reading [r] or writing [w]'->putline;
(if getNonBlank = 'w' then write -> lmode;
else read -> lmode;
if);
'The policy to be guaranteed: MRSW allowed [y,n]'->putline;
(if getNonBlank = 'y' then shared -> lpolicy;
else exclusive ->lpolicy;
if);
mytrans: ps.transaction
(# LockMode::<(# do lmode->value#);
LockPolicy::<(# do lpolicy->value #);
abort::<(# do leave mytrans #);
getregister:(# rootname:^text;
do
'Which register? '-> screen.puttext;
keyboard.getline->rootname[];
(rootname[],register##)->get->s[];
exit s[]
#);
do
commandLoop: cycle
(#
newreg:^register;
do
'Get a register (persistent root) [g]'->putline;
'Display register [d]'->putline;
'Find person in register [f]'->putline;
'Add person to register [a]'->putline;
'Delete person from register [k]'->putline;
'Change name of person [c]'->putline;
'Show registers in location [s]'->putline;
'Put register [p]'->putline;
'Remove register [r]'->putline;
'Checkpoint/Update persistent store [u]'->putline;
'Reget in-memory objects [e]'->putline;
'Abort the transaction [b]'->putline;
'Commit the transaction [q]'->putline;
(if getNonBlank
// 'g' then
getregister->s[];
(if (not (s[] = NONE)) then
'Done'->putline;
if);
// 'd' then
getregister->s[];
(if (not (s[] = NONE)) then
screen[]->s.display;
if);
// 'f' then
getregister->s[];
(if (not (s[] = NONE)) then
findWithKey (# do screen[] -> found.display #);
if);
// 'a' then
getregister->s[];
(if (not (s[] = NONE)) then
addPerson;
if);
// 'k' then
getregister->s[];
(if (not (s[] = NONE)) then
delete
if);
// 'c' then
getregister->s[];
(if (not (s[] = NONE)) then
change;
if);
// 's' then
'The following registers are found in the PS:'
->putline;
scanrootnames (# do current[]->putline; #);
// 'p' then
'Name of register to be put? '-> screen.puttext;
keyboard.getline->rootname[];
®ister[]->newreg[];
(newreg[],rootname.copy)->put;
// 'r' then
getregister->s[];
(if (not (s[] = NONE)) then
NONE->s[];
if);
// 'e' then
reget;
// 'u' then
checkpoint;
// 'b' then
abort;
// 'q' then
leave commandLoop;
if);
#);
#);
'Continue with new transaction [yn]?'->screen.puttext;
(if getnonblank = 'y' then
restart transactionloop
if);
#);
(* close shared persistent store *)
(*********************************)
PS.close;
theShell.kill;
#);
#) |