We report below the code of the AIOCJ choreography where a rule introduces a new role (logger) in the adapted scope.
preamble {
starter: client
}
aioc {
product@client = getInput( "Insert product name" );
request: client( product ) -> seller ( order );
scope @seller{
// process the order and compute result, here XXX
result@seller = "XXX";
response: seller( result ) -> client( result )
}
}
rule {
include log from "socket://localhost:8002" with "jsonrpc"
include getTime from "socket://localhost:8003" with "jsonrpc"
newRoles: logger
on { N.apply != false } // applicability conditions, irrelevant in this example
do{
log: seller( order ) -> logger( entry );
{
time@logger = getTime();
_@logger = log( time + ": " + entry )
} | {
result@seller = "XXX";
response: seller( result ) -> client ( result )
}
}
}
// scope adaptation synchronisation procedure
var5.sid = "3dd7e775-7006-4a96-b07f-cfa920183575";
var5.rolesNum = 2;
var5.hasAck = true;
Leader.location = "socket://localhost:10501/";
initStartProcedure@Leader( var5 );
undef( var5.rolesNum );
undef( var5.hasAck );
startSR.name = "execute";
acquire@SemaphoreUtils( startSR )( );
joinStart@Leader( var5 )( );
aReq.client = "socket://localhost:10501/";
aReq.ports.seller.address = "socket://localhost:10501/";
aReq.ports.client.address = "socket://localhost:10500/";
// adaptation request
checkForUpdate@AdaptationManager( aReq )( aRes );
// if adaptation is required
if ( is_defined( aRes ) ) {
for ( c = 0, c < #aRes.roles.seller.code, c++ ){
embed_scope@ActivityManager( aRes.roles.seller.code[ c ] )( )
};
var4.sid = adaptRequest.main_key = aRes.main_key;
foreach ( r : aRes.roles ){
var4.rolesNum++
};
var4.hasAck = true;
initStartProcedure@Leader( var4 );
var4.sid = "3dd7e775-7006-4a96-b07f-cfa920183575_adapt";
undef( var4.hasAck );
initStartProcedure@Leader( var4 );
undef( var4.rolesNum );
undef( aRes.roles.seller );
// distribute the adaptation code to all participants (roles) ...
foreach ( roleName : aRes.roles ){
if ( is_defined( aRes.roles.( roleName ).cookie ) ) {
adaptRequest.cookie = aRes.roles.( roleName ).cookie;
LedRole.location = aRes.roles.( roleName ).location;
op0.msgID = adaptRequest.cookie;
op0.content.sid = "3dd7e775-7006-4a96-b07f-cfa920183575_adapt";
op0.content.leader = Leader.location;
coord@LedRole( op0 )( )
} else {
adaptRequest.cookie = "3dd7e775-7006-4a96-b07f-cfa920183575";
LedRole.location = aRes.roles.( roleName ).location + "!/Activity/3dd7e775-7006-4a96-b07f-cfa920183575"
};
adaptRequest.code << aRes.roles.( roleName ).code;
adapt@LedRole( adaptRequest )( );
undef( adaptRequest.code )
};
joinStart@Leader( var4 )( );
// ... and execute your own
run@ActivityManager( aRes.main_key )( )
} else {
// no adaptation, execute original code
eReq.cookie = "3dd7e775-7006-4a96-b07f-cfa920183575";
noAdapt@client( eReq );
var0 = "XXX";
var1.value = var0;
var1 = "result";
set@State( var1 )( );
get@State( "result" )( var3 );
_tmp = var3;
var2.content = _tmp;
var2.msgID = "973caa7c-0bc9-4f5e-8455-eb3047ced1bd";
response@client( var2 )( )
};
// scope execution terminated, returning to the parent choreography
var6.sid = "3dd7e775-7006-4a96-b07f-cfa920183575";
joinAck@Leader( var6 )( );
startActivity@ActivityManager( "3dd7e775-7006-4a96-b07f-cfa920183575" );
startSR.name = "done";
release@SemaphoreUtils( startSR )( )
// gets the entry log from the seller
var0.msgID = "9751af6e-277a-47ad-b272-f6b6f904ed2e";
get_log@MH( var0 )( var0 );
var1 = var0.content;
var2.value = var1;
var2 = "entry";
set@State( var2 )( );
{
// contacts the getTime service
getTime@Port1( var3 )( var4 );
var5.value = var4;
var5 = "time";
set@State( var5 )( );
// prepare the message to the logger service
get@State( "entry" )( var6 );
get@State( "time" )( var7 );
var8.p[0] = var7 + ": " + var6;
// send the message to the logger service
log@Port0( var8 )( var9 );
var10.value = var9;
var10 = "_";
set@State( var10 )( )
}