4 Tutorial Examples

4.1 Create a global store

The following code shows how to create a new Global Store GS. The imported module GlobalStore implements the GS abstraction. The procedure NewStore from the GlobalStore module initialises a GS and offers the Ls reference in a file or a URL.

Source File

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Create a new global store
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
functor 
import 
   GlobalStore(newStore:NewStore)    
   Connection
   Pickle
   System(show:Show)
define 
   Ls
   try 
      {NewStore ?Ls}
      % pickle LS and offer it to clients
      {Pickle.save {Connection.offerUnlimited Ls $} './gsticket'}
   catch 
      gs(failed_globalstore_creation) then 
      {Show errorNewStore }      
   [] error(url(_ _) debug:_) then {Show 'cannot create url or file '}
   [] error(connection(_ _)  debug:_)  then {Show 'connection Module error'}
   end 
end 

4.2 Create a new connected user to the GS

The following functor creates a new user named user1 connected to the GS. The newLocal method returns a LocalStore reference to the GS and a NewObj procedure for creating new objects in the GS. The call throws a gs(connectionfailed) exception if it fails to connect to GS. In the current release of the GS module, NewObj is a sited reference i.e it cannot be exported to others users. Each new user will create its own NewObj reference. Each user has the ability of creating other users by exporting its LocalStore reference on distant sites.

Source File

functor  
import 
  Connection
  System(show:Show)
  Pickle
define         
  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 
end 

4.3 Create objects in the global store

We show how to create three counter objects in the global store:

Source File

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Create an object in the store
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Obj1 Obj2 Obj3 are references in
%  the local  store  
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
declare 
class Counter 
   attr val
   meth show(Value) Value=@val end 
   meth inc(Value) val <- @val+Value end 
   meth init(Value) val <- Value end   
end 
Obj1 Obj2 Obj3
in 
Obj1={NewObj  Counter init(0)}
Obj2={NewObj  Counter  init(0)}
Obj3={NewObj  Counter  init(0)}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Save  Obj1 reference to use it on other users
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%{LocalStore saveobj(Obj1 'obj1')}

4.4 Initialise transactions

A transaction is a one argument procedure initiated in its own thread. The variable Out is a return value of Trans.

Source File

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Initialise transactions
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
proc{Trans Out}
   if {IsOdd {Obj1 show($)}}  
      {Obj1 inc(1)}
      {Obj1 inc(~1)}
      {Obj2 inc(~1)}        
      {Obj2 inc(2)}
   else 
      skip 
   end 
   Out=state({Obj1 show($)})
end    
OutPut  % Output of Trans
Transid % Transaction Identifier
in 
   {LocalStore trans(Trans ?OutPut ?Transid)}  
   %%%% check transaction
   %%%% The result is commit, abort  
   {System.show {LocalStore checktrans(Transid $)}}

4.5 Coherent Snapshot of the store

We use a transaction to have values of objects GS values. The values are globally coherent if Trans is committed.

Source File

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Procedure to show a coherent
% snapshot of the global store
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
proc {CoherentSnapshot}        
   proc{Trans ?Output}
      Val1 Val2 Val3 in 
      {Obj1 show(Val1)}  
      {Obj2 show(Val2)}
      {Obj3 show(Val3)}
      Output=state(Val1 Val2 Val3)
   end 
   Transid
   Out
   Result
in      
   {LocalStore trans(Trans ?Out ?Transid)}
   {LocalStore checktrans(Trid Result _)}                  
   if Result==commit  then 
      {Show 'Obj1:'#Out.1#'Obj2:'#Out.2#'Obj3:'#Out.3}
   else 
      skip 
   end          
    
end   

4.6 Concurrent updates inside a transaction

We introduce concurrency inside a transaction at a user by the call {LocalStore newthread(proc {$} {Obj1 inc(1)} end)}. The call executes the procedure proc {$} {Obj1 inc(1)} end in its own thread.

Source File

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Initialise transactions
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
proc{Trans Out}
          
   {Obj1 inc(1)}
   {Obj1 inc(~1)}
   {Obj2 inc(~1)}
   %%% Update is done in a new thread
   {LocalStore newthread(proc {$}  {Obj1 inc(1)} end)}
   %%%%        
   {Obj2 inc(2)}
   {Obj1 inc(1)}
   Out=state({Obj1 show($)})
end    
OutPut  % Output of Trans
Transid % Transaction Identifier
Res
in 
   {LocalStore trans(Trans OutPut ?Transid)}  
   %%%% check transaction
   %%%% The result is commit, abort  
   {LocalStore checktrans(Transid Res _)}
   {System.show Res}
 

4.7 Synchonous waiting for object locks

To avoid speculative computations, we offer a synchronization procedure to wait for locks on GS objects. If a user has a lock on a GS object say O, all its local modifications on O become global (broadcasted to all users). Here is an example of transaction that waits for Obj1 and Obj2 locks before performing the updates.

Source File

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Initialise transactions
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
proc{Trans Out}
   % Synchronous waiting for locks on Obj1 Obj2
   % if lock obtained -> ok
   % else Trans aborted
   {LocalStore waitlocks([Obj1 Obj2])}  
   {Obj1 inc(1)}
   {Obj1 inc(~1)}
   {Obj2 inc(~1)}      
   {Obj2 inc(2)}
   {Obj1 inc(1)}
   Out=state({Obj1 show($)})
end    
OutPut  % Output of Trans
Transid % Transaction Identifier
Res
in 
   {LocalStore trans(Trans OutPut ?Transid)}  
   %%%% check transaction
   %%%% The result is commit, abort  
   {LocalStore checktrans(Transid Res _)}
   {System.show Res}
 

4.8 Migrate store location

To enhance the reliability of GS, users can choose a specific site where the new GS will be moved. A user can migrate the GS to a specific host. This is useful for load balancing or to reduce communication latency with current GS home site. The call {Movehere Module ?LS Proc} migrates the GS from its current home site to the site where Movehere is executed and returns the new reference to the store after migration. After the end of store migration, all dependencies with the home site are removed.

Source File

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% migrate the global store  
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
{Movehere Module _ proc{$skip end }

By using the setactionmigration, the LS new store reference can be pickled and saved in a file. New clients can connect through this pickled reference.


Mostafa AL-Metwally, Ilies Alouini
Version 1.2.0 (20010319)