<< Prev | - Up - | Next >> |
GlobalStore
Demo examplesIn this chapter we'll present some concrete applications which use some functionality provided by this package.
The application example is a multi-user drawing application. Each user have its own drawing area. A user draws rectangles on the drawing area and moves them with the mouse. The abstraction maintains the coherence of all user's display. The following original centralised program uses the QTk Module. It shows how graphics objects can be controlled on a canvas. We can create rectangles, click on them and drag them with the mouse.
functor
import
QTk
export
define
Canvas
Desc=td(canvas( handle:Canvas
glue:nswe
bg:white))
Window={QTk.build Desc}
ListColors= [red green blue yellow]
Colors={NewCell ListColors}
proc{CreateRectangle X Y}
Tag
Col
in
Tag={Canvas newTag($)}
case {Access Colors $} of
Color|_ then Col=Color
[] nil then {Assign Colors ListColors} Col=red
end
{Assign Colors {List.drop {Access Colors $} 1 $}}
{Canvas create(rectangle X-50 Y-50 X+50 Y+50 fill:Col tags:Tag)}
{Bindevent Tag}
end
proc {Bindevent Tag}
{Tag bind(event:"<B1-ButtonRelease>"
args:[int(x) int(y)]
action:proc{$ X Y}
{Tag setCoords(X-50 Y-50 X+50 Y+50)}
end)}
end
{Canvas bind(event:"<2>"
args:[int(x) int(y) ]
action:CreateRectangle)}
in
{Window show(wait:true)}
end
To make the drawing program a fault tolerant distributed application, the original centralised program is modified in the following way: First, we create a new global store.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Create a new global store
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
functor
import
OS
Open
GlobalStore(newStore:NewStore)
Application
Connection
Pickle
System(show:Show)
define
Pid F
Ls
%%% Store emulator pid in a file : user by the test failure script
try
Pid={OS.getPID}
F={New Open.file init(name:'/tmp/pidserver' flags:[write create])}
{F write(vs:Pid)}
{F close}
catch
error(_)
then
{Show 'ErrorCreateFile'}
end
try
{NewStore ?Ls}
% pickle LS and offer it to clients
{Pickle.save {Connection.offerUnlimited Ls $} './gsticket'}
catch
gs(failed_globalstore_creation) then
{Show errorNewStore }{Application.exit 0}
[] error(url(_ _) debug:_) then {Show 'cannot create url or file '}
[] error(connection(_ _) debug:_) then {Show 'connection Module error'}
end
end
Second, we modify the original centralised code by connecting the new user to the global store and using transactions when we update rectangle objects.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Example illustrating the GS
%% Author Ilies Alouini
%% Last Modification 9-9-2000
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
functor
import
System(show:Show)
Module
Pickle
Connection
Application
export
define
%%% rectangle object class in the Global Store
class Rectangle
prop locking
attr
ox:0
oy:0
order
color
meth init(X Y Order Color)
ox <- X
oy <- Y
order <- Order
color <- Color
end
meth getcoord(X Y)
lock
X=@ox
Y=@oy
end
end
meth setcoord(X Y)
lock
ox <- X
oy <- Y
end
end
meth getorder(O)
O=@order
end
meth getcolor(Col)
Col=@color
end
end
[QTk]={Module.link ["./QTk.ozf"]}
Canvas
Desc=td(canvas(
handle:Canvas
glue:nswe
bg:white))
%tdscrollbar:true
%lrscrollbar:true))
Window={QTk.build Desc}
%%%%%%% Dictionary of pairs order store object, store object#graphic object
Dictobjects={NewDictionary $}
NewObj LocalStore Movehere LS
ListColors= [red green blue yellow]
Colors={NewCell ListColors}
proc{UpdateRectangle X Y Obj ?Tag}
Tag={Canvas newTag($)}
{Canvas create(rectangle X-50 Y-50 X+50 Y+50 fill:{Obj getcolor($)} tags:Tag)}
{Bindevent Tag Obj}
end
proc{CreateRectangle X Y}
Order Sobj
Tag
Col
in
Tag={Canvas newTag($)}
case {Access Colors $} of
Color|_ then Col=Color
[] nil then {Assign Colors ListColors} Col=red
end
{Assign Colors {List.drop {Access Colors $} 1 $}}
try
Sobj={NewObj Rectangle init(X Y Order Col)}
{Canvas create(rectangle X-50 Y-50 X+50 Y+50 fill:Col tags:Tag)}
{LocalStore getuniqueident(?Order)}
{Dictionary.put Dictobjects Order Sobj#Tag}
{Bindevent Tag Sobj}
catch gs(global_store_temporary_failed) then
{Show 'Object not created: retry'}
end
end
proc {Bindevent Tag Sobj}
{Tag bind(event:"<B1-ButtonRelease>"
args:[int(x) int(y)]
action:proc{$ X Y}
Out Transid
proc {Trans Output}
{Sobj setcoord(X Y)}
end
in
%{Canvas canvasx(OX ?X)}
%{Canvas canvasy(OY ?Y)}
{Tag setCoords(X-50 Y-50 X+50 Y+50)}
% initialise transaction on Tag
{LocalStore trans(Trans Out Transid)}
%{LocalStore checktrans(Transid Res _)}
end)}
end
{Canvas bind(event:"<2>"
args:[int(x) int(y) ]
action:CreateRectangle)}
RedrawAll
in
%%%%%%%%%%%%%%%%%%%%%%%%%
%% Initiate a local store
%%%%%%%%%%%%%%%%%%%%%%%%%
try LS={Connection.take {Pickle.load './gsticket' $}}
catch
error(url(_ _) debug:_) then {Show 'url or file not found'}
[] error(connection(_ _) debug:_) then {Show connectionfailed}
end
try
{LS newLocal(Module user1 ?NewObj ?LocalStore ?Movehere)}
catch gs(connectionfailed)
then
{Show connectionfailed}
end
try {Pickle.save {Connection.offerUnlimited LocalStore $} './client1ticket'}
catch
error(url(_ _) debug:_) then {Show 'cannot create url or file '}
[] error(connection(_ _) debug:_) then {Show 'connection Module error'}
end
%%% Save the MOvehere procedure
try {Pickle.save {Connection.offerUnlimited Movehere $} './movehereticket'}
catch
error(url(_ _) debug:_) then {Show 'cannot create url or file '}
[] error(connection(_ _) debug:_) then {Show 'connection Module error'}
end
% set action when object creation
{LocalStore setnotifycreation(
proc {$ O}
Tag X Y Ord in
{O getorder(Ord)}
{Wait Ord}
{O getcoord(X Y)}
{UpdateRectangle X Y O ?Tag}
{Dictionary.put Dictobjects Ord O#Tag}
end)}
%%%% Redraw All Objects
proc {RedrawAll}
Entries En in
% sort Graphic objects
{Dictionary.keys Dictobjects ?Entries}
{List.sort Entries Value.'<' ?En}
% redraw all objects in order
{ForAll En
proc {$ Order}
O X Y Tag Go in
{Dictionary.get Dictobjects Order O#Go}
{Go delete}
{O getcoord(X Y)}
{UpdateRectangle X Y O ?Tag}
{Dictionary.remove Dictobjects Order}
{Dictionary.put Dictobjects Order O#Tag}
end
}
end
% set action when receiving Obj object update
{LocalStore setnotifyupdate(
proc {$ ?Obj}
{RedrawAll}
end)
}
{LocalStore setnotifyabort(
proc {$ ?Obj}
{RedrawAll}
end
)
}
{Window show(wait:true)}
end
We can now create another new user connected to GS:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Example illustrating the GS
%% Author Ilies Alouini
%% Last Modification 9-9-2000
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
functor
import
System(show:Show)
Module
Application
Connection
Pickle
export
define
%%% rectangle object class in the Global Store
class Rectangle
prop locking
attr
ox:0
oy:0
order
color
meth init(X Y Order Color)
ox <- X
oy <- Y
order <- Order
color <- Color
end
meth getcoord(X Y)
lock
X=@ox
Y=@oy
end
end
meth setcoord(X Y)
lock
ox <- X
oy <- Y
end
end
meth getorder(O)
O=@order
end
meth getcolor(Col)
Col=@color
end
end
[QTk]={Module.link ["./QTk.ozf"]}
Canvas
Desc=td(canvas(
handle:Canvas
glue:nswe
bg:white))
%tdscrollbar:true
%lrscrollbar:true))
Window={QTk.build Desc}
%%%%%%% Dictionary of pairs order store object, store object#graphic object
Dictobjects={NewDictionary $}
NewObj LocalStore LS Movehere
ListColors= [red green blue yellow]
Colors={NewCell ListColors}
proc{UpdateRectangle X Y Obj ?Tag}
Tag={Canvas newTag($)}
{Canvas create(rectangle X-50 Y-50 X+50 Y+50 fill:{Obj getcolor($)} tags:Tag)}
{Bindevent Tag Obj}
end
proc{CreateRectangle X Y}
Order Sobj
Tag
Col
in
Tag={Canvas newTag($)}
case {Access Colors $} of
Color|_ then Col=Color
[] nil then {Assign Colors ListColors} Col=red
end
{Assign Colors {List.drop {Access Colors $} 1 $}}
try
Sobj={NewObj Rectangle init(X Y Order Col)}
{Canvas create(rectangle X-50 Y-50 X+50 Y+50 fill:Col tags:Tag)}
{LocalStore getuniqueident(?Order)}
{Dictionary.put Dictobjects Order Sobj#Tag}
{Bindevent Tag Sobj}
catch gs(global_store_temporary_failed) then
{Show 'Object not created: retry'}
end
end
proc {Bindevent Tag Sobj}
{Tag bind(event:"<B1-ButtonRelease>"
args:[int(x) int(y)]
action:proc{$ X Y}
Out Transid
proc {Trans Output}
{Sobj setcoord(X Y)}
end
in
{Tag setCoords(X-50 Y-50 X+50 Y+50)}
% initialise transaction on Tag
{LocalStore trans(Trans Out Transid)}
%{LocalStore checktrans(Transid Res _)}
end)}
end
{Canvas bind(event:"<2>"
args:[int(x) int(y) ]
action:CreateRectangle)}
RedrawAll
in
%%%%%%%%%%%%%%%%%%%%%%%%%
%% Initiate a local store
%%%%%%%%%%%%%%%%%%%%%%%%%
try LS={Connection.take {Pickle.load './client1ticket' $}}
catch
error(url(_ _) debug:_) then {Show 'url or file not found'}
[] error(connection(_ _) debug:_) then {Show connectionfailed}
end
try
{LS newlocal(Module user1 ?NewObj?LocalStore ?Movehere)}
catch gs(connectionfailed)
then
{Show connectionfailed}
end
% set action when object creation
{LocalStore setnotifycreation(
proc {$ O}
Tag X Y Ord in
{O getorder(Ord)}
{Wait Ord}
{O getcoord(X Y)}
{UpdateRectangle X Y O ?Tag}
{Dictionary.put Dictobjects Ord O#Tag}
end)}
%%%% Redraw All Objects
proc {RedrawAll}
Entries En in
% sort Graphic objects
{Dictionary.keys Dictobjects ?Entries}
{List.sort Entries Value.'<' ?En}
% redraw all objects in order
{ForAll En
proc {$ Order}
O X Y Tag Go in
{Dictionary.get Dictobjects Order O#Go}
{Go delete}
{O getcoord(X Y)}
{Go delete}
{UpdateRectangle X Y O ?Tag}
{Dictionary.remove Dictobjects Order}
{Dictionary.put Dictobjects Order O#Tag}
end
}
end
% set action when receiving Obj object update
{LocalStore setnotifyupdate(
proc {$ ?Obj}
{RedrawAll}
end)
}
{LocalStore setnotifyabort(
proc {$ ?Obj}
{RedrawAll}
end
)
}
{Window show(wait:true)}
end
This example illustrates the use of fine grained transactions to update object counters (see comments in the source code). First, we must create a new global store as it is described in the previous section. Then, we create two users connected to GS.
First user Program:
functor
import
System(show:Show)
OS
Open
Pickle
Connection
Module
define
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Store emulator pid in a file
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
F Pid
try
Pid={OS.getPID}
F={New Open.file init(name:'/tmp/pidclient'#Pid flags:[write create])}
{F write(vs:Pid)}
{F close}
catch
error(_)
then
{Show 'ErrorCreateFile'}
end
%%%%%%%%%%%%%%%%%%%%%%%%%
%% Connect to GS
%%%%%%%%%%%%%%%%%%%%%%%%%
LS
try LS={Connection.take {Pickle.load './gsticket' $}}
catch
error(url(_ _) debug:_) then {Show 'url or file not found'}
[] error(connection(_ _) debug:_) then {Show connectionfailed}
end
NewObj LocalStore Movehere
try
{LS newLocal(Module user1 ?NewObj ?LocalStore ?Movehere)}
catch gs(connectionfailed)
then
{Show connectionfailed}
end
try {Pickle.save {Connection.offerUnlimited LocalStore $} './client1ticket'}
catch
error(url(_ _) debug:_) then {Show 'cannot create url or file '}
[] error(connection(_ _) debug:_) then {Show 'connection Module error'}
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Create objects in the store:
% Obj1 Obj2 Obj3 are references in
% the LocalStore
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
class Counter
attr val
meth show(Value) Value=@val end
meth inc(Value)
val <- @val+Value
%{Obj3 dec(1)}
end
meth dec(Value)
val <- @val-Value
end
meth init(Value) val <- Value end
end
Obj1={NewObj Counter init(0)}
Obj2={NewObj Counter init(0)}
Obj3={NewObj Counter init(0)}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Save Obj1 reference to use it on other clients
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
try {LocalStore saveobj(Obj1 '/usr/staff/ila/=Oz/store/o1globalref')}
catch
gs(use_localstore_localreference) then {Show 'cannot apply methods on remote clients'}
[] error(url(_ _) debug:_) then {Show 'cannot create url or file '}
[] error(connection(_ _) debug:_) then {Show 'connection Module error'}
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Procedure to show a coherent
% snapshot of the global store
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
proc {CoherentSnapshot}
C={NewCell 0}
proc{Trans Output}
Val1 Val2 Val3 in
{Obj1 show(Val1)}
{Obj2 show(Val2)}
{Obj3 show(Val3)}
Output=state(Val1 Val2 Val3)
end
Trid
Out
Res
in
% State of objects Obj1 Obj2 is coherent here
% show state of objects in a file after 1mn of period
if {OS.time $} - {Access C $}>=20
then
%Localstore may raise the exception:
% gs(use_localstore_localreference)
% gs(undefinedmethod#Meth)
% gs(invalidcall) % for waitlocks, retrans, newthread, {O M}
{LocalStore trans(Trans Out ?Trid)} % raise gs(ill_formed_transaction)
{LocalStore checktrans(Trid Res _)}
if Res==commit then
{Show 'Obj1:'#Out.1#'Obj2:'#Out.2#'Obj3:'#Out.3}
else
skip
end
{Assign C {OS.time $}}
else
skip
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Initialise transactions
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
LastTransid
fun {Iterate I}
Transid Retransid
proc{Trans Out}
proc {Iteratebis J}
if J\=0
then
%{LocalStore waitlocks([Obj1 Obj2])}
{Obj1 inc(1)}
{Obj1 inc(~1)}
%{LocalStore newthread(proc {$} {Show 'newthread'} {Obj1 inc(1)} end)}
%if {IsEven {Obj1 show($)}}==true
% then
{Obj2 inc(~1)}
{Obj2 inc(2)}
% else
% skip
%end
{Obj1 inc(1)}
{Obj1 inc(~1)}
{Obj1 inc(1)}
{Obj1 inc(~1)}
{Obj1 inc(1)}
%{LocalStore waitlocks([Obj3 Obj1])}
{Obj3 inc(1)}
{Iteratebis J-1}
else
skip
end
end
OutPut
in
{Iteratebis 1}
% {LocalStore retrans(
% proc {$ Out}
% {Obj1 inc(1)}
% {Obj3 inc(1)}
% end
% OutPut
% ?Retransid)
% }
end
Out
in
if I\=0
then
{LocalStore trans(Trans Out ?Transid)}
%{Delay 1}
if I==1 then
LastTransid=Transid
%LastTransid=Retransid
else
skip
end
(Transid#Transid)|{Iterate I-1}
%(Transid#Retransid)|{Iterate I-1}
else
nil
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Migrate the global store
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%thread
% {Delay 15000}
% {Movehere Module _ proc{$} skip end }
%end
Transset={Iterate 2000}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Wait for the end of transactions and updates
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%{Wait {LocalStore checktrans(LastTransid $ _)}} % For transactions
{Wait {LocalStore termination($)}} % For updates
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Compute number of committed/aborted transactions
%% Compute number of committed/aborted retransactions
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Ccommit={NewCell 0} Cabort={NewCell 0}
Crcommit={NewCell 0} Crabort={NewCell 0}
Crecompute={NewCell 0} Crrecompute={NewCell 0}
{ForAll Transset
proc{$ Pair}
Tr RTr Res Resb Nb Nbr in
if Pair\=nil then
Pair=Tr#RTr
{LocalStore checktrans(Tr ?Res ?Nb)}
{Assign Crecompute {Access Crecompute $}+Nb}
if Res==commit
then
{Assign Ccommit {Access Ccommit $}+1}
else
{Assign Cabort {Access Cabort $}+1}
end
if {Access Ccommit $}+{Access Cabort $}==2000 then
{Show 'Number of local committed transaction:'#{Access Ccommit $}}
{Show 'Number of local aborted transaction:'#{Access Cabort $}}
{Show 'Number of local recomputed transaction:'#{Access Crecompute $}}
else
skip
end
if {IsFree RTr} then
Resb=abort % Thread terminated before executing retrans
Nbr=0
else
{LocalStore checktrans(RTr Resb Nbr)}
end
{Assign Crrecompute {Access Crrecompute $}+Nbr}
if Resb==commit
then
{Assign Crcommit {Access Crcommit $}+1}
else
{Assign Crabort {Access Crabort $}+1}
end
if {Access Crcommit $}+{Access Crabort $}==2000 then
{Show 'Number of local aborted retrans:'#{Access Crabort $}}
{Show 'Number of local committed retrans :'#{Access Crcommit $}}
{Show 'Number of local recomputed retrans:'#{Access Crrecompute $}}
else
skip
end
else
skip
end
end
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Show states of objects
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
{CoherentSnapshot}
end
Second user Program:
functor
import
System(show:Show)
OS
Open
Connection
Pickle
Module
Application
define
class Counter
attr val
meth show(Value) Value=@val end
meth inc(Value) val <- @val+Value end
meth init(Value) val <- Value end
end
%%% Store emulator pid in a file
F Pid
try
Pid={OS.getPID}
F={New Open.file init(name:'/tmp/pidclient'#Pid flags:[write create])}
{F write(vs:Pid)}
{F close}
catch
error(_)
then
{Show 'ErrorCreateFile'}
end
%%% deamon to simulate site failure
%{OS.system "deamon" _}
%%%
%%%%%%%%%%%%%%%%%%%%%%%%%
%% Initiate a local store
%%%%%%%%%%%%%%%%%%%%%%%%%
LS
try LS={Connection.take {Pickle.load './client1ticket' $}}
catch
error(url(_ _) debug:_) then {Show 'url or file not found'}
[] error(connection(_ _) debug:_) then {Show connectionfailed}
end
LocalStore NewObjInStore Movehere
try
{LS newLocal(Module user1 ?NewObjInStore ?LocalStore ?Movehere)}
catch gs(connectionfailed)
then
{Show connectionfailed}
end
{Delay 15000}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Create an object in the store
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Obj1 Obj2 Obj3
Obj3={NewObjInStore Counter init(0)}
Obj2={NewObjInStore Counter init(0)}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Get the local reference of an object
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
try
{LocalStore getobj('/usr/staff/ila/=Oz/store/o1globalref' ?Obj1)}
catch
gs(objectlost) then {Show 'object lost'}
[] error(url(_ _) debug:_) then {Show 'url or file not found'}
[] error(connection(_ _) debug:_) then {Show 'connection Module error'}
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Procedure to show a coherent
% snapshot of the global store
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CoherentSnapshot
proc {CoherentSnapshot}
C={NewCell 0}
proc{Trans Output}
Val1 Val2 Val3 in
{Obj1 show(Val1)}
{Obj2 show(Val2)}
{Obj3 show(Val3)}
Output=state(Val1 Val2 Val3)
end
Trid
Out
Res
in
% State of objects Obj1 Obj2 is coherent here
% show state of objects in a file after 1mn of period
if {OS.time $} - {Access C $}>=20
then
{LocalStore trans(Trans Out ?Trid)}
{LocalStore checktrans(Trid Res _)}
if Res==commit then
{Show 'Obj1:'#Out.1#'Obj2:'#Out.2#'Obj3:'#Out.3}
else
skip
end
{Assign C {OS.time $}}
else
skip
end
end
%%%%%%%%%%%%%%%%%%%
% Init transactions
%%%%%%%%%%%%%%%%%%%
Transset Iterate
fun {Iterate I}
Transid Iteratebis Retransid
proc{Trans Out}
proc {Iteratebis J}
if J\=0
then
{Obj1 inc(1) }
{Obj2 inc(~1)}
{Iteratebis J-1}
else
skip
end
end
in
%{LocalStore waitlocks([Obj1 Obj3])}
%{LocalStore newthread(proc {$} {Show 'newthread'} {Obj1 inc(1)} end)}
{Iteratebis 1}
{Obj1 inc(1) }
{Obj1 inc(~1) }
{Obj1 inc(1) }
{Obj1 inc(~1) }
{Obj1 inc(1) }
{Obj3 inc(1) }
end
Out
in
if I\=0
then
{LocalStore trans(Trans Out Transid)}
{Delay 60}
Transid#Transid|{Iterate I-1}
else
nil
end
end
Transset={Iterate 1000}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Compute number of committed/aborted transactions
%% Wait for the end of transactions and updates ..
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
{Wait {LocalStore termination($)}} %
Ccommit={NewCell 0} Cabort={NewCell 0} Crcommit={NewCell 0}
Crabort={NewCell 0}
Crecompute={NewCell 0} Crrecompute={NewCell 0}
{ForAll Transset
proc{$ Pair}
Tr RTr Res Resb Nb Nbr in
if Pair\=nil then
Pair=Tr#RTr
{LocalStore checktrans(Tr Res Nb)}
{Assign Crecompute {Access Crecompute $}+Nb}
if Res==commit
then
{Assign Ccommit {Access Ccommit $}+1}
else
{Assign Cabort {Access Cabort $}+1}
end
if {Access Ccommit $}+{Access Cabort $}==1000 then
{Show 'Number of local committed transaction:'#{Access Ccommit $}}
{Show 'Number of local aborted transaction:'#{Access Cabort $}}
{Show 'Number of local recomputed transaction:'#{Access Crecompute $}}
else
skip
end
{LocalStore checktrans(RTr Resb Nbr)}
{Assign Crrecompute {Access Crrecompute $}+Nbr}
if Resb==commit
then
{Assign Crcommit {Access Crcommit $}+1}
else
{Assign Crabort {Access Crabort $}+1}
end
if {Access Crcommit $}+{Access Crabort $}==1000 then
{Show 'Number of local aborted retrans :'#{Access Crabort $}}
{Show 'Number of local committed retrans :'#{Access Crcommit $}}
{Show 'Number of local recomputed retrans:'#{Access Crrecompute $}}
else
skip
end
else
skip
end
end
}
{CoherentSnapshot}
end
NOT YET COMPLETED
<< Prev | - Up - | Next >> |