فهرست منبع

Put execution of SC in background task

Yentl Van Tendeloo 8 سال پیش
والد
کامیت
27ae497bb6
4فایلهای تغییر یافته به همراه69 افزوده شده و 73 حذف شده
  1. 1 3
      interface/PDEVS/console.py
  2. 16 11
      wrappers/classes/modelverse.xml
  3. 37 48
      wrappers/modelverse.py
  4. 15 11
      wrappers/modelverse_SCCD.py

+ 1 - 3
interface/PDEVS/console.py

@@ -2,7 +2,6 @@ import sys
 sys.path.append("../../wrappers")
 from modelverse import *
 import random, re, json
-from interface import Controller
 from pprint import pprint
 from multiprocessing import Process, Pipe, freeze_support
 
@@ -86,8 +85,6 @@ def start_pypdevs_client(conn):
     except ModelExists:
         pass
 
-    controller = Controller()
-    
     print("Starting PyPDEVS client...")
     transformation_execute_AL("models/paralleldevs_simulator", {"MyString": "models/example_PS_DEVS_String"}, {}, fetch_output=False)
         
@@ -244,6 +241,7 @@ if __name__ == '__main__':
     except ModelExists:
         pass
     
+    from interface import Controller
     controller = Controller()
 
     def set_defaults(inp, defaultlist):

+ 16 - 11
wrappers/classes/modelverse.xml

@@ -74,12 +74,9 @@
 
     <method name="expect_input">
         <parameter name="context"/>
-        <parameter name="expected"/>
         <body>
-            if isinstance(expected, list):
-                return self.inputs[context] and self.inputs[context][0]["name"] in expected
-            else:
-                return self.inputs[context] and self.inputs[context][0]["name"] == expected
+            print("Expect_input for %s" % self.inputs[context])
+            return len(self.inputs[context]) > 0
         </body>
     </method>
 
@@ -168,7 +165,7 @@
                         </raise>
                         <script>
                             self.responses.append(json.loads(data))
-                            #print("Got data: " + str(json.loads(data)))
+                            print("Got data %s for %s." % (json.loads(data), self.taskname))
                         </script>
                     </transition>
 
@@ -180,11 +177,18 @@
                         </raise>
                         <script>
                             self.responses.append(json.loads(data))
+                            print("Got final data %s for %s." % (json.loads(data), self.taskname))
                         </script>
                     </transition>
                 </state>
 
-                <state id="finished"/>
+                <state id="finished">
+                    <onentry>
+                        <script>
+                            print("Finished output thread")
+                        </script>
+                    </onentry>
+                </state>
             </state>
 
             <state id="behaviour" initial="wait_for_action">
@@ -691,6 +695,7 @@
                                     </raise>
                                     <script>
                                         if self.parameters[4] == False:
+                                            print("Finish output thread")
                                             self.finish_output_thread = True
                                     </script>
                                 </onentry>
@@ -720,9 +725,9 @@
                                     </raise>
                                 </transition>
 
-                                <transition cond="self.expect_input(self.input_context, 'data_input')" target=".">
+                                <transition cond="self.expect_input(self.input_context)" target=".">
                                     <raise event="request">
-                                        <parameter expr="self.inputs[self.input_context].pop(0)['parameters']"/>
+                                        <parameter expr="self.inputs[self.input_context].pop(0)"/>
                                     </raise>
                                 </transition>
                             </state>
@@ -817,9 +822,9 @@
                                             </raise>
                                         </transition>
 
-                                        <transition cond="self.expect_input(self.input_context, 'data_input')" target=".">
+                                        <transition cond="self.expect_input(self.input_context)" target=".">
                                             <raise event="request">
-                                                <parameter expr="self.inputs[self.input_context].pop(0)['parameters']"/>
+                                                <parameter expr="self.inputs[self.input_context].pop(0)"/>
                                             </raise>
                                         </transition>
                                     </state>

+ 37 - 48
wrappers/modelverse.py

@@ -52,6 +52,39 @@ def _next_ID():
     ID += 1
     return ID
 
+def _process_SC(statechart, port_sc, context):
+    print("Context: " + str(context))
+    while 1:
+        empty = True
+
+        # Fetch output from the MV
+        response = responses.fetch(0)
+        if response is not None:
+            print("Output of MV to SC")
+            if response.name == "data_output":
+                # Got output of MV, so forward to SCCD
+                statechart[0].addInput(Event("input", statechart[1], response.parameters))
+            elif response.name == "result":
+                # Finished execution, so continue and return result
+                statechart[0].addInput(Event("terminate", statechart[1], []))
+                return response.parameters[1]
+            else:
+                raise Exception("Unknown data from MV to SC: " + str(response))
+            empty = False
+
+        # Fetch output from the SC
+        response = port_sc.fetch(0)
+        if response is not None:
+            print("Output of SC to MV")
+            if response.name == "output":
+                controller.addInput(Event("data_input", "action_in", [response.parameters, context]))
+            else:
+                raise Exception("Unknown data from SC to MV: " + str(response))
+            empty = False
+
+        if empty:
+            time.sleep(0.5)
+
 def INPUT(action, context, parameters):
     controller.addInput(Event("action", "action_in", [action, _next_ID(), context, parameters]))
 
@@ -176,64 +209,20 @@ def transformation_execute_MT(operation_name, input_models_dict, output_models_d
     INPUT("transformation_execute_MT", None, [operation_name, input_models_dict, output_models_dict, tracability_model, fetch_output])
     context = OUTPUT()
     if statechart is not None:
-        while 1:
-            empty = True
-
-            # Fetch output from the MV
-            response = responses.fetch(0)
-            if response is not None:
-                if response.name == "data_output":
-                    # Got output of MV, so forward to SCCD
-                    statechart[0].addInput(Event("input", statechart[1], response.parameters))
-                elif response.name == "result":
-                    # Finished execution, so continue and return result
-                    statechart[0].addInput(Event("terminate", statechart[1], []))
-                    return response.parameters[1]
-                empty = False
-
-            # Fetch output from the SC
-            response = port_sc.fetch(0)
-            if response is not None:
-                if response.name == "output":
-                    controller.addInput(Event("data_input", "action_in", [response.parameters, context]))
-                empty = False
-
-            if empty:
-                time.sleep(0.01)
+        threading.Thread(target=_process_SC, args=[statechart, port_sc, context]).start()
     else:
         return OUTPUT()
 
 def transformation_execute_AL(operation_name, input_models_dict, output_models_dict, statechart=None, tracability_model="", fetch_output=True):
     if statechart is not None:
+        print("Connecting to SC...")
         port_sc = statechart[0].addOutputListener(statechart[2])
+        print("Connected to port " + str(statechart[2]))
     INPUT("transformation_execute_AL", None, [operation_name, input_models_dict, output_models_dict, tracability_model, fetch_output])
 
     context = OUTPUT()
     if statechart is not None:
-        while 1:
-            empty = True
-
-            # Fetch output from the MV
-            response = responses.fetch(0)
-            if response is not None:
-                if response.name == "data_output":
-                    # Got output of MV, so forward to SCCD
-                    statechart[0].addInput(Event("input", statechart[1], response.parameters))
-                elif response.name == "result":
-                    # Finished execution, so continue and return result
-                    statechart[0].addInput(Event("terminate", statechart[1], []))
-                    return response.parameters[1]
-                empty = False
-
-            # Fetch output from the SC
-            response = port_sc.fetch(0)
-            if response is not None:
-                if response.name == "output":
-                    controller.addInput(Event("data_input", "action_in", [response.parameters, context]))
-                empty = False
-
-            if empty:
-                time.sleep(0.01)
+        threading.Thread(target=_process_SC, args=[statechart, port_sc, context]).start()
     else:
         return OUTPUT()
 

+ 15 - 11
wrappers/modelverse_SCCD.py

@@ -1,7 +1,7 @@
 """
 Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van Mierlo, and Yentl Van Tendeloo (for the inspiration)
 
-Date:   Tue Oct 31 14:39:52 2017
+Date:   Mon Nov  6 09:05:16 2017
 
 Model author: Yentl Van Tendeloo
 Model name:   MvK Server
@@ -108,11 +108,9 @@ class Modelverse(RuntimeClassBase):
     
     
     # user defined method
-    def expect_input(self, context, expected):
-        if isinstance(expected, list):
-            return self.inputs[context] and self.inputs[context][0]["name"] in expected
-        else:
-            return self.inputs[context] and self.inputs[context][0]["name"] == expected
+    def expect_input(self, context):
+        print("Expect_input for %s" % self.inputs[context])
+        return len(self.inputs[context]) > 0
     
     
     # builds Statechart structure
@@ -140,6 +138,7 @@ class Modelverse(RuntimeClassBase):
         
         # state /initialized/http_mapper/finished
         self.states["/initialized/http_mapper/finished"] = State(6, "/initialized/http_mapper/finished", self)
+        self.states["/initialized/http_mapper/finished"].setEnter(self._initialized_http_mapper_finished_enter)
         
         # state /initialized/behaviour
         self.states["/initialized/behaviour"] = State(7, "/initialized/behaviour", self)
@@ -1962,6 +1961,9 @@ class Modelverse(RuntimeClassBase):
         self.big_step.outputEventOM(Event("create_instance", None, [self, 'http_client', 'HTTPClient']))
         self.big_step.outputEventOM(Event("create_instance", None, [self, 'http_client', 'HTTPClient']))
     
+    def _initialized_http_mapper_finished_enter(self):
+        print("Finished output thread")
+    
     def _initialized_behaviour_operations_model_list_enter(self):
         self.raiseInternalEvent(Event("request", None, [['model_list', self.parameters[0]]]))
     
@@ -2033,6 +2035,7 @@ class Modelverse(RuntimeClassBase):
     def _initialized_behaviour_operations_store_on_scripted_transformation_execute_send_operation_enter(self):
         self.raiseInternalEvent(Event("request", None, [['transformation_execute', self.parameters[0]] + self.dict_to_list(self.parameters[1]) + self.dict_to_list(self.parameters[2]) + [self.parameters[3]]]))
         if self.parameters[4] == False:
+            print("Finish output thread")
             self.finish_output_thread = True
     
     def _initialized_behaviour_operations_store_on_scripted_transformation_execute_MANUAL_send_metadata_enter(self):
@@ -2421,7 +2424,7 @@ class Modelverse(RuntimeClassBase):
         data = parameters[0]
         self.big_step.outputEventOM(Event("narrow_cast", None, [self, self.http_clients[1], Event("HTTP_input", None, [urllib.urlencode({"op": "get_output", "taskname": self.taskname}), "parent"])]))
         self.responses.append(json.loads(data))
-        #print("Got data: " + str(json.loads(data)))
+        print("Got data %s for %s." % (json.loads(data), self.taskname))
     
     def _initialized_http_mapper_init_3_guard(self, parameters):
         data = parameters[0]
@@ -2431,6 +2434,7 @@ class Modelverse(RuntimeClassBase):
         data = parameters[0]
         self.big_step.outputEventOM(Event("narrow_cast", None, [self, self.http_clients[1], Event("HTTP_input", None, [urllib.urlencode({"op": "get_output", "taskname": self.taskname}), "parent"])]))
         self.responses.append(json.loads(data))
+        print("Got final data %s for %s." % (json.loads(data), self.taskname))
     
     def _initialized_http_mapper_init_4_guard(self, parameters):
         data = parameters[0]
@@ -2674,10 +2678,10 @@ class Modelverse(RuntimeClassBase):
         return not (self.expect_response('Success', pop=False) or self.expect_response('Failure', pop=False)) and self.expect_response_partial('', pop=False)
     
     def _initialized_behaviour_operations_store_on_scripted_transformation_execute_dialog_2_exec(self, parameters):
-        self.raiseInternalEvent(Event("request", None, [self.inputs[self.input_context].pop(0)['parameters']]))
+        self.raiseInternalEvent(Event("request", None, [self.inputs[self.input_context].pop(0)]))
     
     def _initialized_behaviour_operations_store_on_scripted_transformation_execute_dialog_2_guard(self, parameters):
-        return self.expect_input(self.input_context, 'data_input')
+        return self.expect_input(self.input_context)
     
     def _initialized_behaviour_operations_store_on_scripted_transformation_execute_MANUAL_send_metadata_0_guard(self, parameters):
         return self.expect_response('Success: ready for MANUAL execution')
@@ -2733,10 +2737,10 @@ class Modelverse(RuntimeClassBase):
         return not (self.expect_response('Success', pop=False) or self.expect_response('Failure', pop=False)) and self.expect_response_partial('', pop=False)
     
     def _initialized_behaviour_operations_store_on_scripted_process_execute_enacting_sc_processing_1_exec(self, parameters):
-        self.raiseInternalEvent(Event("request", None, [self.inputs[self.input_context].pop(0)['parameters']]))
+        self.raiseInternalEvent(Event("request", None, [self.inputs[self.input_context].pop(0)]))
     
     def _initialized_behaviour_operations_store_on_scripted_process_execute_enacting_sc_processing_1_guard(self, parameters):
-        return self.expect_input(self.input_context, 'data_input')
+        return self.expect_input(self.input_context)
     
     def _initialized_behaviour_operations_store_on_scripted_process_execute_enacting_op_init_0_exec(self, parameters):
         self.context = str(uuid.uuid4())