Generalize from_pid to find_simulation

This allows searching for a sim by any of its parameters over the
multicate channel.
This commit is contained in:
Derek Bankieris 2019-11-04 11:22:48 -06:00
parent c35ca93830
commit 2d89023031

View File

@ -533,7 +533,7 @@ class VariableServer(object):
# - appending to the variables list while
# update_variables is executing does not invalidate
# the length check
# - izip is bounded by the number of values, and the
# - zip is bounded by the number of values, and the
# length check ensures there are at least as many
# variables as values
self._variables.append(variable)
@ -568,11 +568,11 @@ class VariableServer(object):
self._var_clear()
# No lock is needed here because:
# - This assignment is atomic.
# - If update_variables has already called izip, the list it is
# - If update_variables has already called zip, the list it is
# ierating over is unchanged as we're assigning a new list
# here instead of clearing the shared reference.
# - If update_variables has not yet called izip, when it does,
# izip will return an empty generator, terminating the loop.
# - If update_variables has not yet called zip, when it does,
# zip will return an empty generator, terminating the loop.
self._variables = []
def set_units(self, name, units):
@ -1029,16 +1029,43 @@ class VariableServer(object):
self._asynchronous_socket.close()
self._thread.join()
def from_pid(pid, timeout=None):
def __str__(self):
return 'VariableServer' + str(self._synchronous_socket.getpeername())
def find_simulation(host=None, port=None, user=None, pid=None,
version=None, sim_directory=None, s_main=None,
input_file=None, tag=None, timeout=None):
"""
Connect to the simulation at the given pid. This is done by
listening on the multicast channel over which all sims broadcast
their existance.
Listen for simulations on the multicast channel over which all sims broadcast
their existance. Connect to the one that matches the provided arguments that
are not None.
If there are multiple matches, connect to the first one we happen to find.
If all arguments are None, connect to the first sim we happen to find.
Such matches will be non-deterministic.
Parameters
----------
host : str
Host name of the machine on which the sim is running as reported by
Trick.
port : int
Variable Server port.
user : str
Simulation process user.
pid : int
The sim's process ID.
version : str
Trick version.
sim_directory : str
SIM_* directory. If this starts with /, it will be considered an
absolute path.
s_main : str
Filename of the S_main* executeable. Not an absolute path.
input_file : str
Path to the input file relative to the simDirectory.
tag : str
Simulation tag.
timeout : positive float or None
How long to look for the sim before giving up. Pass None to wait
indefinitely.
@ -1046,7 +1073,8 @@ def from_pid(pid, timeout=None):
Returns
-------
VariableServer
A VariableServer connected to the sim at pid.
A VariableServer connected to the sim matcthing the specified
parameters.
Raises
------
@ -1060,9 +1088,18 @@ def from_pid(pid, timeout=None):
sock.setsockopt(
socket.IPPROTO_IP,
socket.IP_ADD_MEMBERSHIP,
struct.pack("=4sl", socket.inet_aton('224.3.14.15'), socket.INADDR_ANY))
struct.pack('=4sl', socket.inet_aton('224.3.14.15'), socket.INADDR_ANY))
file_interface = sock.makefile()
def candidate_matches(candidate):
for parameter, candidate_parameter in zip(
[host, port, user, pid, sim_directory,
s_main, input_file, version, tag],
candidate) :
if parameter is not None and str(parameter) != candidate_parameter:
return False
return True
# the socket will clean itself up when it's garbage-collected
while True:
if timeout is not None:
@ -1072,9 +1109,22 @@ def from_pid(pid, timeout=None):
clock = time.time()
sock.settimeout(timeout)
host, port, _, process_id = file_interface.readline().split('\t')[:4]
if int(process_id) == int(pid):
return VariableServer(host, port)
# 0: host
# 1: port
# 2: user
# 3: pid
# 4: SIM_*
# 5: S_main*
# 6: RUN_*
# 7: version
# 8: tag
candidate = file_interface.readline().split('\t')[:9]
if not str(sim_directory).startswith('/'):
candidate[4] = os.path.basename(candidate[4])
if candidate_matches(candidate):
return VariableServer(candidate[0], candidate[1])
def _parse_value(text):
"""