123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 |
- <class name="MvKController">
- <relationships>
- <association name="to_mvs" class="HTTPClient" min="1" max="1"/>
- <association name="to_mvi" class="Server" min="1" max="1"/>
- <association name="users" class="UserStatechart"/>
- <association name="executor" class="Executor" min="1" max="1"/>
- </relationships>
- <constructor>
- <parameter name="params"/>
- <body>
- <![CDATA[
- self.users = []
- self.user_statecharts = {"__hierarchy": None}
- self.input_queue = []
- self.user_queue = {}
- self.source = None
- self.root = None
- self.params = params
- ]]>
- </body>
- </constructor>
- <scxml initial="init_server">
- <state id="init_server">
- <onentry>
- <raise scope="cd" event="create_instance">
- <parameter expr="'to_mvi'"/>
- <parameter expr="'Server'"/>
- <parameter expr="''"/>
- <parameter expr="8001"/>
- </raise>
- </onentry>
- <transition event="instance_created" target="../init_executor">
- <parameter name="instancename"/>
- <raise scope="cd" event="start_instance">
- <parameter expr="instancename"/>
- </raise>
- </transition>
- </state>
- <state id="init_executor">
- <onentry>
- <raise scope="cd" event="create_instance">
- <parameter expr="'executor'"/>
- <parameter expr="'Executor'"/>
- </raise>
- </onentry>
- <transition event="instance_created" target="../get_mvk">
- <parameter name="instancename"/>
- <raise scope="cd" event="start_instance">
- <parameter expr="instancename"/>
- </raise>
- </transition>
- </state>
- <state id="get_mvk">
- <onentry>
- <raise event="get_mvk" scope="narrow" target="'executor'">
- <parameter expr="'parent'"/>
- </raise>
- </onentry>
- <transition event="get_mvk_reply" target="../read_root">
- <parameter name="mvk"/>
- <script>
- self.mvk = mvk
- </script>
- </transition>
- </state>
- <state id="read_root">
- <onentry>
- <raise event="raw_exec" scope="narrow" target="'executor'">
- <parameter expr="[['RR', []]]"/>
- <parameter expr="'parent'"/>
- </raise>
- </onentry>
- <transition event="raw_exec_reply" target="../running">
- <parameter name="data"/>
- <script>
- self.root = data[0][0]
- </script>
- </transition>
- </state>
- <parallel id="running">
- <state id="wait_for_requests">
- <state id="wait">
- <transition event="from_mvi" target=".">
- <parameter name="source"/>
- <parameter name="data"/>
- <script>
- # No JSON encoding necessary, as it is not complex
- print("Got from MVI")
- try:
- args = None
- if data["op"] == "set_input":
- if "value" in data:
- value = [json.loads(data["value"])]
- else:
- value = json.loads(data["data"])
- for v in value[:-1]:
- self.input_queue.append((None, data["op"], [v], data["username"]))
- self.input_queue.append((source, data["op"], [value[-1]], data["username"]))
- print("Added to input queue")
- else:
- print("Appending " + data["op"])
- self.input_queue.append((source, data["op"], args, data["username"]))
- except ValueError:
- print("Error when deserializing request: " + str(data))
- raise
- </script>
- </transition>
- </state>
- </state>
- <state id="push" initial="wait">
- <state id="wait">
- <transition cond="self.input_queue and self.input_queue[0][3] in self.user_statecharts" target="../process"/>
- <!-- User is not yet detected, so stall this message -->
- <transition cond="self.input_queue and self.input_queue[0][3] not in self.user_statecharts" target=".">
- <!-- Move it to the back of the list, so we can process other users first -->
- <script>
- print("Queue user")
- self.user_queue.setdefault(self.input_queue[0][3], []).append(self.input_queue.pop(0))
- </script>
- <!-- Force a refresh too -->
- <raise event="force_user_refresh"/>
- </transition>
- </state>
- <state id="process">
- <transition cond="self.input_queue[0][1] == 'set_input'" target="../wait">
- <script>
- source, op, args, username = self.input_queue.pop(0)
- </script>
- <raise event="set_input" scope="narrow" target="self.user_statecharts[username]">
- <parameter expr="source"/>
- <parameter expr="args"/>
- </raise>
- </transition>
- <transition cond="self.input_queue[0][1] == 'get_output'" target="../wait">
- <script>
- source, op, args, username = self.input_queue.pop(0)
- </script>
- <raise event="get_output" scope="narrow" target="self.user_statecharts[username]">
- <parameter expr="source"/>
- <parameter expr="args"/>
- </raise>
- </transition>
-
- <transition cond="self.input_queue[0][1] == 'pause'" target="../wait">
- <script>
- print("Sending pause")
- source, op, args, username = self.input_queue.pop(0)
- </script>
- <raise event="pause" scope="narrow" target="self.user_statecharts[username]">
- <parameter expr="source"/>
- <parameter expr="args"/>
- </raise>
- </transition>
-
- <transition cond="self.input_queue[0][1] == 'resume'" target="../wait">
- <script>
- source, op, args, username = self.input_queue.pop(0)
- </script>
- <raise event="resume" scope="narrow" target="self.user_statecharts[username]">
- <parameter expr="source"/>
- <parameter expr="args"/>
- </raise>
- </transition>
- </state>
- </state>
- <state id="find_users" initial="get_all_links">
- <state id="get_all_links">
- <onentry>
- <raise event="raw_exec" scope="narrow" target="'executor'">
- <parameter expr="[['RDK', [self.root]]]"/>
- <parameter expr="'parent'"/>
- </raise>
- </onentry>
- <transition event="raw_exec_reply" target="../retrieve_users">
- <parameter name="data"/>
- <script>
- self.users = data[0][0]
- </script>
- </transition>
- </state>
- <state id="retrieve_users">
- <transition cond="self.users" target="../got_usernames">
- <raise event="raw_exec" scope="narrow" target="'executor'">
- <parameter expr="[['RV', [user]] for user in self.users]"/>
- <parameter expr="'parent'"/>
- </raise>
- </transition>
- <transition cond="not self.users" target="../wait"/>
- </state>
- <state id="got_usernames">
- <transition event="raw_exec_reply" target="../process_users">
- <parameter name="data"/>
- <script>
- data = set([v[0] for v in data])
- self.add_users = [v for v in data if v not in self.user_statecharts]
- self.delete_users = [v for v in self.user_statecharts if v not in data]
- </script>
- </transition>
- </state>
- <state id="process_users">
- <transition cond="not self.add_users and not self.delete_users" target="../wait"/>
- <transition cond="self.add_users and not self.delete_users" target="../creating_user">
- <raise event="create_instance" scope="cd">
- <parameter expr="'users'"/>
- <parameter expr="'UserStatechart'"/>
- <parameter expr="self.add_users[0]"/>
- <parameter expr="self.mvk"/>
- </raise>
- </transition>
- <transition cond="self.delete_users" target=".">
- <raise event="delete_instance" scope="cd">
- <parameter expr="self.user_statecharts.pop(self.delete_users.pop(0))"/>
- </raise>
- </transition>
- </state>
- <state id="creating_user">
- <transition event="instance_created" target="../retrieve_users">
- <parameter name="instancename"/>
- <raise scope="cd" event="start_instance">
- <parameter expr="instancename"/>
- </raise>
- <raise scope="narrow" target="instancename" event="set_returnpath">
- <parameter expr="instancename"/>
- </raise>
- <script>
- self.user_statecharts[self.add_users[0]] = instancename
- # Repush all this user's messages in the input queue
- self.input_queue.extend(self.user_queue.pop(self.add_users[0], []))
- self.add_users.pop(0)
- </script>
- </transition>
- </state>
- <state id="wait">
- <transition after="1.0" target="../get_all_links"/>
- <transition event="force_user_refresh" target="../get_all_links"/>
- </state>
- </state>
- </parallel>
- </scxml>
- </class>
|