123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 |
- <class name="MvKController">
- <relationships>
- <association name="to_mvi" class="Server" min="1" max="1"/>
- </relationships>
- <constructor>
- <parameter name="params"/>
- <body>
- <![CDATA[
- self.mvs = ModelverseState("../bootstrap/bootstrap.m")
- self.root = self.mvs.read_root()[0]
- self.mvk = ModelverseKernel(self.root)
- self.all_failed = False
- self.timeout = False
- self.users = set()
- self.input_queue = defaultdict(list)
- self.output_queue = defaultdict(list)
- self.source = None
- self.port = int(sys.argv[1])
- self.mvs_operations = {
- "CN": self.mvs.create_node,
- "CE": self.mvs.create_edge,
- "CNV": self.mvs.create_nodevalue,
- "CD": self.mvs.create_dict,
- "RV": self.mvs.read_value,
- "RO": self.mvs.read_outgoing,
- "RI": self.mvs.read_incoming,
- "RE": self.mvs.read_edge,
- "RD": self.mvs.read_dict,
- "RDN": self.mvs.read_dict_node,
- "RDNE": self.mvs.read_dict_node_edge,
- "RDE": self.mvs.read_dict_edge,
- "RRD": self.mvs.read_reverse_dict,
- "RR": self.mvs.read_root,
- "RDK": self.mvs.read_dict_keys,
- "DE": self.mvs.delete_edge,
- "DN": self.mvs.delete_node,
- }
- self.execute_modelverse("", "load_primitives", [])
- ]]>
- </body>
- </constructor>
- <method name="execute_modelverse">
- <parameter name="username"/>
- <parameter name="operation"/>
- <parameter name="params"/>
- <body>
- <![CDATA[
- reply = None
- commands = []
- while 1:
- commands = self.mvk.execute_yields(username, operation, params, reply)
- if commands is None:
- break
- reply = [self.mvs_operations[command[0]](*(command[1]))[0] for command in commands]
- if len(reply) == 1:
- reply = reply[0]
- ]]>
- </body>
- </method>
- <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="self.port"/>
- </raise>
- </onentry>
- <transition event="instance_created" target="../running">
- <parameter name="instancename"/>
- <raise scope="cd" event="start_instance">
- <parameter expr="instancename"/>
- </raise>
- </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
- if data["op"] == "set_input":
- if "element_type" in data:
- if data["element_type"] == "V":
- value = json.loads(data["value"])
- else:
- value = data["value"]
- args = [data["element_type"], value]
- self.input_queue[data["username"]].append((source, [args]))
- else:
- d = []
- for t, v in json.loads(data["data"]):
- if t == "V":
- v = json.loads(v)
- d.append([t, v])
- self.input_queue[data["username"]].append((source, d))
- elif data["op"] == "get_output":
- self.output_queue[data["username"]].append(source)
- else:
- raise Exception("DROPPING unknown operation: " + str(data["op"]))
- </script>
- </transition>
- </state>
- </state>
- <state id="execution">
- <state id="execution">
- <onentry>
- <script>
- self.timeout = False
- self.destination = None
- if self.users:
- user = self.users.pop()
- # Check if there are values to input
- if self.input_queue[user]:
- source, args = self.input_queue[user].pop(0)
- for args_entry in args:
- self.execute_modelverse(user, "set_input", args_entry)
- self.destination = source
- self.value = {"id": 200, "value": "OK"}
- self.all_failed = False
- # Now process for some steps, or until we are again blocked for input
- for x in xrange(200):
- self.execute_modelverse(user, "execute_rule", [])
- if not self.mvk.success:
- # Blocking or broken, so quit already to stop wasting CPU
- break
- self.all_failed = False
- # Check that we don't have anything to output yet, otherwise we wait
- if self.destination is None:
- # Perform output if there is anything
- if self.output_queue[user]:
- self.execute_modelverse(user, "get_output", [])
- if self.mvk.success:
- self.destination = self.output_queue[user].pop(0)
- self.value = self.mvk.returnvalue
- self.all_failed = False
- else:
- out = self.mvs.read_outgoing(self.root)[0]
- for m in out:
- src, user = self.mvs.read_edge(m)[0]
- outgoing = self.mvs.read_outgoing(m)[0]
- first = self.mvs.read_edge(outgoing[0])[0]
- dest = first[1]
- name = self.mvs.read_value(dest)[0]
- if name.startswith("__"):
- continue
- self.users.add(name)
- self.timeout = self.all_failed
- self.all_failed = True
- </script>
- </onentry>
- <transition cond="self.destination is not None" after="0" target=".">
- <raise event="HTTP_input" scope="narrow" target="'to_mvi/%s' % self.destination">
- <parameter expr="self.value"/>
- </raise>
- </transition>
- <transition cond="self.timeout and self.destination is None" after="0.1" target="."/>
- <transition cond="not self.timeout and self.destination is None" after="0" target="."/>
- </state>
- </state>
- <state id="remove_sockets">
- <state id="remove_sockets">
- <transition event="delete_socket" target=".">
- <parameter name="socket"/>
- <script>
- for user in self.output_queue.keys():
- self.output_queue[user] = [s for s in self.output_queue[user] if s != socket]
- </script>
- </transition>
- </state>
- </state>
- </parallel>
- </scxml>
- </class>
|