blob: e2f46d5f808b6a07ac452919272c5dfe7ce7da54 [file] [log] [blame]
[comment encoding = UTF-8 /]
[comment
-----------------------------------------------------------------------
-- Ada infrastructural code generator --
-- for the CHESS component model --
-- --
-- Copyright (C) 2011-2012 --
-- University of Padova, ITALY --
-- --
-- Author: Marco Panunzio panunzio@math.unipd.it --
-- --
-- All rights reserved. This program and the accompanying materials --
-- are made available under the terms of the Eclipse Public License --
-- v1.0 which accompanies this distribution, and is available at --
-- http://www.eclipse.org/legal/epl-v20.html --
-----------------------------------------------------------------------
/]
[module RemoteMsgServer('http://www.eclipse.org/uml2/3.0.0/UML', 'http://www.eclipse.org/papyrus/GCM/1')]
[import org::polarsys::chess::codegen::ada::main::Copyright /]
[template public generateRemoteMsgServer(model : Model, procNode: InstanceSpecification, compInstInputList : Sequence(OclAny), connectorInstInputList: Sequence(OclAny)) {
procNodeName : String = procNode.name;
clSvPortStName : String = 'MARTE::MARTE_DesignModel::GCM::ClientServerPort';
assignStName : String = 'MARTE::MARTE_Foundations::Alloc::Assign';
compImplStName : String = 'CHESS::ComponentModel::ComponentImplementation';
chHwProcessorStName : String = 'CHESS::Predictability::DeploymentConfiguration::HardwareBaseline::CH_HwProcessor';
isSingleNodeSystem : Boolean = isSingleNodeSystem(InstanceSpecification.allInstances()->asSequence(), chHwProcessorStName);
compInstList : Sequence(InstanceSpecification) = compInstInputList->filter(InstanceSpecification);
requiredInterfaceSlotList : Sequence(Slot) = getRequiredInterfaceSlotList(compInstList, clSvPortStName)->filter(Slot);
providedInterfaceSlotList : Sequence(Slot) = getProvidedInterfaceSlotList(compInstList, clSvPortStName)->filter(Slot);
connectorInstList : Sequence(InstanceSpecification) = connectorInstInputList->filter(InstanceSpecification);
isRemoteMsgServerNecessary : Boolean = isRemoteMsgServerNecessary(providedInterfaceSlotList, procNode, connectorInstList, Comment.allInstances()->asSequence(), assignStName);
}
]
[comment RemoteMsgServer.ads /]
[if (isRemoteMsgServerNecessary)]
[file (procNodeName.concat('/middleware/src/remote_msg_server.ads').toLower(), false, 'UTF-8')]
[generateCopyrightAda(model)/]
with YAMI.Core.Closed_Connection_Handlers;
with YAMI.Core.Incoming_Message_Handlers;
with YAMI.Core.New_Connection_Handlers;
with Remote_Msg_Server_Task;
with Data_Structure;
with Middleware_Realtime_Attribute;
with Datatype; use Datatype;
-- with of RI to be called
[for (sl : Slot | providedInterfaceSlotList)]
[let boundSlot : Sequence(Slot) = getBoundRIslotList(sl, connectorInstList)->filter(Slot)]
[if (isRemoteCommNecessary(boundSlot, procNode, Comment.allInstances()->asSequence(), assignStName))]
with [getProvidedInterface(sl.definingFeature->filter(Port)->asSequence()->first(), clSvPortStName).name/];
[/if]
[/let]
[/for]
package Remote_Msg_Server is
procedure Initialize_Remote_Msg_Server;
procedure Run;
type Incoming_Message_Handler is
new YAMI.Core.Incoming_Message_Handlers.Handler with null record;
type New_Connection_Handler is
new YAMI.Core.New_Connection_Handlers.Handler with null record;
type Closed_Connection_Handler is
new YAMI.Core.Closed_Connection_Handlers.Handler with null record;
overriding
procedure New_Connection (H : in out New_Connection_Handler;
Source : in String;
Channel : in YAMI.Core.Channel_Descriptor);
overriding
procedure Closed_Connection (H : in out Closed_Connection_Handler;
Source : in String);
overriding
procedure Call (H : in out Incoming_Message_Handler;
Source : in String;
Header_Buffers : in YAMI.Core.Serialization_Buffers_Descriptor;
Body_Buffers : in YAMI.Core.Serialization_Buffers_Descriptor);
-- Setters for PI redirectors
[for (sl : Slot | providedInterfaceSlotList)]
[let boundSlot : Sequence(Slot) = getBoundRIslotList(sl, connectorInstList)->filter(Slot)]
[if (isRemoteCommNecessary(boundSlot, procNode, Comment.allInstances()->asSequence(), assignStName))]
procedure Set_[sl.definingFeature.name/](ptr : in [getProvidedInterface(sl.definingFeature->filter(Port)->asSequence()->first(), clSvPortStName).name/].[getProvidedInterface(sl.definingFeature->filter(Port)->asSequence()->first(), clSvPortStName).name/]_ptr);
[/if]
[/let]
[/for]
private
procedure Resolve_Call;
-- Instantiation of a thread for the server
Remote_Msg_Server_Thread_0 : aliased
Remote_Msg_Server_Task.Thread_T(Data_Structure.Generate_Task_ID,
Middleware_Realtime_Attribute.Remote_Msg_Server_Priority,
Middleware_Realtime_Attribute.Remote_Msg_Server_Period,
Remote_Msg_Server.Initialize_Remote_Msg_Server'Access,
Remote_Msg_Server.Run'Access);
-- List of PI redirector
[for (sl : Slot | providedInterfaceSlotList)]
[let boundSlot : Sequence(Slot) = getBoundRIslotList(sl, connectorInstList)->filter(Slot)]
[if (isRemoteCommNecessary(boundSlot, procNode, Comment.allInstances()->asSequence(), assignStName))]
[sl.definingFeature.name/]_ptr : [getRequiredInterface(boundSlot.definingFeature->filter(Port)->asSequence()->first(), clSvPortStName).name/].[getRequiredInterface(boundSlot.definingFeature->filter(Port)->asSequence()->first(), clSvPortStName).name/]_ptr;
[/if]
[/let]
[/for]
end Remote_Msg_Server;
[/file]
[comment RemoteMsgServer.adb /]
[file (procNodeName.concat('/middleware/src/remote_msg_server.adb').toLower(), false, 'UTF-8')]
[generateCopyrightAda(model)/]
with YAMI.Core.Agents;
with YAMI.Parameters;
with Ada.Text_IO;
with Distribution_Naming_Data; use Distribution_Naming_Data;
with CRC_lib;
with Interfaces;
package body Remote_Msg_Server is
Client_Target : String (1 .. YAMI.Core.Agents.Max_Target_Length);
Client_Target_Last : Natural;
Server_Agent : YAMI.Core.Agents.Agent;
--Server_Address : constant String := "tcp://localhost:12207";
New_Connection_Called : Boolean := False;
pragma Volatile (New_Connection_Called);
pragma Warnings (Off, New_Connection_Called);
Incoming_Header : YAMI.Parameters.Parameters_Collection;
Incoming_Body : YAMI.Parameters.Parameters_Collection;
Closed_Connection_Called : Boolean := False;
pragma Volatile (Closed_Connection_Called);
pragma Warnings (Off, Closed_Connection_Called);
My_New_Connection_Handler : aliased New_Connection_Handler;
My_Closed_Connection_Handler : aliased Closed_Connection_Handler;
My_Incoming_Message_Handler : aliased Incoming_Message_Handler;
procedure New_Connection (H : in out New_Connection_Handler;
Source : in String;
Channel : in YAMI.Core.Channel_Descriptor) is
pragma Warnings(Off, H);
pragma Warnings(Off, Channel);
begin
Client_Target_Last := Source'Length;
Client_Target (1 .. Client_Target_Last) := Source;
New_Connection_Called := True;
Ada.Text_IO.Put_Line("New Connection called");
end New_Connection;
procedure Closed_Connection (H : in out Closed_Connection_Handler;
Source : in String) is
pragma Warnings(Off, H);
begin
pragma Assert (Source = Client_Target (1 .. Client_Target_Last));
Closed_Connection_Called := True;
Ada.Text_IO.Put_Line("Closed_Connection called");
end Closed_Connection;
procedure Call
(H : in out Incoming_Message_Handler;
Source : in String;
Header_Buffers : in YAMI.Core.Serialization_Buffers_Descriptor;
Body_Buffers : in YAMI.Core.Serialization_Buffers_Descriptor) is
--Destination_Instance : YAMI.Parameters.YAMI_Integer;
--Operation_Name : Ada.Strings.Unbounded.Unbounded_String;
pragma Warnings (Off, H);
begin
Ada.Text_IO.Put_Line("Remote msg server Call called");
-- pragma Assert (Source = Client_Target (1 .. Client_Target_Last));
Incoming_Header.Deserialize (Header_Buffers);
Incoming_Body.Deserialize (Body_Buffers);
Ada.Text_IO.Put_Line("Source: " & Source);
Ada.Text_IO.Put_Line("Destination_Instance: " & Integer'Image(Integer(Incoming_Body.Get_Integer("Destination_Instance_Name"))));
Ada.Text_IO.Put_Line("Instance_Operation_Name: " & Integer'Image(Integer(Incoming_Body.Get_Integer("Instance_Operation_Name"))));
Resolve_Call;
end Call;
procedure Initialize_Remote_Msg_Server is
Resolved_Target : String (1 .. YAMI.Core.Agents.Max_Target_Length);
Resolved_Target_Last : Natural;
Timed_Out : Boolean;
begin
-- Ada.Text_IO.Put_Line("Remote_Msg_Server: Init called");
YAMI.Core.Agents.Init_Agent
(Server_Agent,
My_Incoming_Message_Handler'Unchecked_Access,
My_Closed_Connection_Handler'Unchecked_Access);
-- Ada.Text_IO.Put_Line("Remote_Msg_Server: Agent initialized");
YAMI.Parameters.Init_Parameters (Incoming_Header);
YAMI.Parameters.Init_Parameters (Incoming_Body);
-- Ada.Text_IO.Put_Line("Remote_Msg_Server: Parameters initialized");
Server_Agent.Do_Some_Work (0.0, Timed_Out);
-- create listener
-- Ada.Text_IO.Put_Line("Remote_Msg_Server: Creating listener...");
Server_Agent.Add_Listener
("tcp://127.0.0.1:12207", Resolved_Target, Resolved_Target_Last,
My_New_Connection_Handler'Unchecked_Access);
-- Ada.Text_IO.Put_Line("Remote_Msg_Server: Listener initialized");
Server_Agent.Do_Some_Work (0.0, Timed_Out);
end Initialize_Remote_Msg_Server;
procedure Run is
Timed_Out : Boolean;
begin
--Ada.Text_IO.Put_Line("Run called");
Server_Agent.Do_Some_Work (100.0, Timed_Out);
end Run;
[for (sl : Slot | providedInterfaceSlotList)]
[let boundSlot : Sequence(Slot) = getBoundRIslotList(sl, connectorInstList)->filter(Slot)]
[if (isRemoteCommNecessary(boundSlot, procNode, Comment.allInstances()->asSequence(), assignStName))]
procedure Set_[sl.definingFeature.name/](ptr : in [getProvidedInterface(sl.definingFeature->filter(Port)->asSequence()->first(), clSvPortStName).name/].[getProvidedInterface(sl.definingFeature->filter(Port)->asSequence()->first(), clSvPortStName).name/]_ptr) is
begin
[sl.definingFeature.name/]_ptr := ptr;
end Set_[sl.definingFeature.name/];
[for (op : Operation | getProvidedInterface((sl.definingFeature.oclAsType(Port)), clSvPortStName).ownedOperation)]
[sl.definingFeature.name/]_[op.name/]_Sequence_ID : Integer := 0;
[/for]
[/if]
[/let]
[/for]
procedure Resolve_Call is
Destination_Instance : constant Integer := Integer(Incoming_Body.Get_Integer("Destination_Instance_Name"));
Instance_Operation_Int : constant Integer := Integer(Incoming_Body.Get_Integer("Instance_Operation_Name"));
Has_Sequence_ID : constant Boolean := Incoming_Header.Get_Boolean("Has_Sequence_ID");
Has_Payload_CRC : constant Boolean := Incoming_Header.Get_Boolean("Has_Payload_CRC");
Is_Sequence_ID_correct : Boolean := true;
Is_Payload_CRC_correct : Boolean := true;
begin
case Destination_Instance is
[for (ci : InstanceSpecification | compInstList)]
when Destination_Instance_Name'Pos([ci.name/]) =>
Ada.Text_IO.Put_Line("DEST: [ci.name/]");
[for (sl : Slot | providedInterfaceSlotList->select(mySl | mySl.owningInstance = ci))]
[let boundSlot : Sequence(Slot) = getBoundRIslotList(sl, connectorInstList)->filter(Slot)]
[if (isRemoteCommNecessary(boundSlot, procNode, Comment.allInstances()->asSequence(), assignStName))]
case Instance_Operation_Int is
[for (op : Operation | getProvidedInterface(sl.definingFeature->filter(Port)->asSequence()->first(), clSvPortStName).ownedOperation)]
when Instance_Operation_Name'Pos([op.name/]) =>
Ada.Text_IO.Put_Line("OP : [op.name/]");
Ada.Text_IO.Put_Line("Calling [ci.name/].[op.name/]");
Ada.Text_IO.Put_Line("Has Sequence ID: " & Boolean'Image(Has_Sequence_ID));
Ada.Text_IO.Put_Line("Has Payload CRC: " & Boolean'Image(Has_Payload_CRC));
if (Has_Sequence_ID) then
Ada.Text_IO.Put_Line("Sequence ID: " & Integer'Image(Integer(Incoming_Header.Get_Integer("Sequence_ID"))));
if ([sl.definingFeature.name/]_[op.name/]_Sequence_ID = Integer(Incoming_Header.Get_Integer("Sequence_ID"))) then
Ada.Text_IO.Put_Line("Message Sequence ID matches the expected value");
[sl.definingFeature.name/]_[op.name/]_Sequence_ID := [sl.definingFeature.name/]_[op.name/]_Sequence_ID + 1;
else
Ada.Text_IO.Put_Line("Wrong Sequence ID in incoming message!");
-- Does not update the Sequence ID counter
-- Flag the failed Sequence ID
Is_Sequence_ID_correct := false;
end if;
end if;
[comment issuing the call to the operation /]
[if (op.ownedParameter->size() = 0) ]
if (Has_Payload_CRC) then
--Calculating CRC from incoming message
CRC_lib.Init;
-- Updating CRC with values of destination and instance
CRC_lib.Update(Destination_Instance);
CRC_lib.Update(Instance_Operation_Int);
-- Comparing fetched Payload CRC with calculated CRC
declare
use type Interfaces.Unsigned_32;
Fetched_Payload_CRC : constant Interfaces.Unsigned_32 := Interfaces.Unsigned_32'Value(Incoming_Header.Get_String("Payload_CRC"));
Calculated_Payload_CRC: constant Interfaces.Unsigned_32 := CRC_lib.Get_Value;
begin
Ada.Text_IO.Put_Line("Fetched Payload CRC: " & Incoming_Header.Get_String("Payload_CRC"));
Ada.Text_IO.Put_Line("Calculated Payload CRC: " & Interfaces.Unsigned_32'Image(Calculated_Payload_CRC));
if (Fetched_Payload_CRC = Calculated_Payload_CRC) then
Ada.Text_IO.Put_Line("CRC test passed.");
else
Ada.Text_IO.Put_Line("CRC test failed.");
Is_Payload_CRC_correct := false;
end if;
end;
end if;
if (Is_Sequence_ID_correct and then Is_Payload_CRC_Correct) then
Ada.Text_IO.Put_Line("Message correctly received. Calling the requested operation.");
[sl.definingFeature.name/]_ptr.[op.name/];
else
Ada.Text_IO.Put_Line("Message discarded due to failed test");
end if;
[else]
declare
[for (p : Parameter | op.ownedParameter)]
[if (p.type.name = 'Float')]
[p.name/] : constant Float := Float((Incoming_Body.Get_Long_Float("[p.name/]")));
[elseif (p.type.name = 'Integer')]
[p.name/] : constant Integer := Integer((Incoming_Body.Get_Integer("[p.name/]")));
[elseif (p.type.name = 'Boolean')]
[p.name/] : constant Boolean := Boolean((Incoming_Body.Get_Boolean("[p.name/]")));
[elseif (p.type->filter(Enumeration)->size() = 1)]
[p.name/] : constant [p.type.name/] := [p.type.name/]'Val(Integer((Incoming_Body.Get_Integer("[p.name/]"))));
[elseif (p.type->filter(DataType)->size() = 1)]
[for (pr : Property | p.type->filter(DataType).attribute)]
[if (p.type.name = 'Float')]
[p.name/]_[pr.name/] : constant Float := Float((Incoming_Body.Get_Long_Float("[p.name/].[pr.name/]")));
[elseif (p.type.name = 'Integer')]
[p.name/]_[pr.name/] : constant Integer := Integer((Incoming_Body.Get_Integer("[p.name/].[pr.name/]")));
[elseif (p.type.name = 'Boolean')]
[p.name/]_[pr.name/] : constant Boolean := Boolean((Incoming_Body.Get_Boolean("[p.name/].[pr.name/]")));
[elseif (pr.type->filter(Enumeration)->size() = 1)]
[p.name/]_[pr.name/] : constant [pr.type.name/] := [pr.type.name/]'Val(Integer((Incoming_Body.Get_Integer("[p.name/].[pr.name/]"))));
[else]
[p.name/]_[pr.name/] : constant [pr.type.name/] := [pr.type.name/]((Incoming_Body.Get_Long_Float("[p.name/].[pr.name/]")));
[/if]
[/for]
[p.name/] : constant [p.type.name/] := ([p.type->filter(DataType).attribute->asSequence()->first().name/] => [p.name/]_[p.type->filter(DataType).attribute->asSequence()->first().name/][for (prop : Property | p.type->filter(DataType).attribute->excluding(p.type->filter(DataType).attribute->asSequence()->first()))],
[prop.name/] => [p.name/]_[prop.name/][/for]);
[/if]
[/for]
begin
if (Has_Payload_CRC) then
--Calculating CRC from incoming message
CRC_lib.Init;
-- Updating CRC with values of destination and instance
CRC_lib.Update(Destination_Instance);
CRC_lib.Update(Instance_Operation_Int);
-- Updating CRC with values of operation parameters
[for (p : Parameter | op.ownedParameter)]
[if (p.type.name = 'Float' or p.type.name = 'Integer' or p.type.name = 'Boolean')]
CRC_lib.Update([p.name/]);
[elseif (p.type->filter(Enumeration)->size() = 1)]
CRC_lib.Update([p.type/]'Pos([p.name/]));
[elseif (p.type->filter(DataType)->size() = 1)]
[for (pr : Property | p.type->filter(DataType).attribute)]
[if ((pr.type.name = 'Float') or (pr.type.name = 'Integer') or (pr.type.name = 'Boolean')) ]
CRC_lib.Update([p.name/].[pr.name/]);
[elseif (pr.type->filter(Enumeration)->size() = 1)]
CRC_lib.Update([pr.type.name/]'Pos([p.name/].[pr.name/]));
[else]
CRC_lib.Update(Float([p.name/].[pr.name/]));
[/if]
[/for]
[/if]
[/for]
-- Comparing fetched Payload CRC with calculated CRC
declare
use type Interfaces.Unsigned_32;
Fetched_Payload_CRC : constant Interfaces.Unsigned_32 := Interfaces.Unsigned_32'Value(Incoming_Header.Get_String("Payload_CRC"));
Calculated_Payload_CRC: constant Interfaces.Unsigned_32 := CRC_lib.Get_Value;
begin
Ada.Text_IO.Put_Line("Fetched Payload CRC: " & Incoming_Header.Get_String("Payload_CRC"));
Ada.Text_IO.Put_Line("Calculated Payload CRC: " & Interfaces.Unsigned_32'Image(Calculated_Payload_CRC));
if (Fetched_Payload_CRC = Calculated_Payload_CRC) then
Ada.Text_IO.Put_Line("CRC test passed.");
else
Ada.Text_IO.Put_Line("CRC test failed.");
Is_Payload_CRC_correct := false;
end if;
end;
end if;
if (Is_Sequence_ID_correct and then Is_Payload_CRC_Correct) then
Ada.Text_IO.Put_Line("Message correctly received. Calling the requested operation.");
[sl.definingFeature.name/]_ptr.[op.name/]([op.ownedParameter->first().name/][for (p: Parameter | op.ownedParameter->excluding(op.ownedParameter->first()))], [p.name/][/for]);
else
Ada.Text_IO.Put_Line("Message discarded due to failed test");
end if;
end;
[/if] [comment parameterNumber /]
[/for] [comment operation/]
when others =>
Ada.Text_IO.Put_Line("Operation not recognized");
end case;
[/if]
[/let]
[/for]
[/for]
when others =>
Ada.Text_IO.Put_Line("Destination instance not recognized");
end case;
end Resolve_Call;
end Remote_Msg_Server;
[/file]
[/if]
[/template]
[query public isSingleNodeSystem(arg0 : Sequence(OclAny), arg1 : String) : Boolean
= invoke('org.polarsys.chess.codegen.ada.service.UML2Service', 'isSingleNodeSystem(java.util.List, java.lang.String)', Sequence{arg0, arg1}) /]
[query public getRequiredInterfaceSlotList(arg0 : Sequence(OclAny), arg1 : String) : Sequence(OclAny)
= invoke('org.polarsys.chess.codegen.ada.service.UML2Service', 'getRequiredInterfaceSlotList(java.util.List, java.lang.String)', Sequence{arg0, arg1}) /]
[query public getProvidedInterface(arg0 : Port, arg1 : String) : Interface
= invoke('org.polarsys.chess.codegen.ada.service.UML2Service', 'getProvidedInterface(org.eclipse.uml2.uml.Port, java.lang.String)', Sequence{arg0, arg1}) /]
[query public getProvidedInterfaceSlotList(arg0 : Sequence(OclAny), arg1 : String) : Sequence(OclAny)
= invoke('org.polarsys.chess.codegen.ada.service.UML2Service', 'getProvidedInterfaceSlotList(java.util.List, java.lang.String)', Sequence{arg0, arg1}) /]
[query public getBoundRIslotList(arg0 : Slot, arg1 : Sequence(OclAny)) : Sequence(OclAny)
= invoke('org.polarsys.chess.codegen.ada.service.UML2Service', 'getBoundRIslotList(org.eclipse.uml2.uml.Slot, java.util.List)', Sequence{arg0, arg1}) /]
[query public isRemoteCommNecessary(arg0: Sequence(OclAny), arg1 : InstanceSpecification, arg2 : Sequence(OclAny), arg3 : String) : Boolean
= invoke('org.polarsys.chess.codegen.ada.service.UML2Service', 'isRemoteCommNecessary(java.util.List, org.eclipse.uml2.uml.InstanceSpecification, java.util.List, java.lang.String)', Sequence{arg0, arg1, arg2, arg3}) /]
[query public isRemoteMsgServerNecessary(arg0: Sequence(OclAny), arg1 : InstanceSpecification, arg2 : Sequence(OclAny), arg3 : Sequence(OclAny), arg4 : String) : Boolean
= invoke('org.polarsys.chess.codegen.ada.service.UML2Service', 'isRemoteMsgServerNecessary(java.util.List, org.eclipse.uml2.uml.InstanceSpecification, java.util.List, java.util.List, java.lang.String)', Sequence{arg0, arg1, arg2, arg3, arg4}) /]
[query public getRequiredInterface(arg0 : Port, arg1 : String) : Interface
= invoke('org.polarsys.chess.codegen.ada.service.UML2Service', 'getRequiredInterface(org.eclipse.uml2.uml.Port, java.lang.String)', Sequence{arg0, arg1}) /]