def latency(self): """ Computes the latency from the latency range. """ # If we're not online then raise an exception. if not self.online: raise NetworkError("Cannot get latency for an offline connection!") # Constant Connections if self.type == CONSTANT: assert isinstance(self._latency, int) return self._latency if not hasattr(self, '_latency_distribution'): assert isinstance(self._latency, (tuple, list)) if self.type == VARIABLE: self._latency_distribution = Uniform(*self._latency) elif self.type == NORMAL: self._latency_distribution = Normal(*self._latency) else: # Something went wrong raise UnknownType("Unkown connection type, {!r}".format( self.type)) # Non-constant connections (Variable, Normal) value = self._latency_distribution.get() # If value is zero or negative, try again if value <= 1: return self.latency() return value
def latency(self): """ Computes the latency from the latency range. """ # If we're not online then raise an exception. if not self.online: raise NetworkError( "Cannot get latency for an offline connection!" ) # Constant Connections if self.type == CONSTANT: assert isinstance(self._latency, int) return self._latency if not hasattr(self, '_latency_distribution'): assert isinstance(self._latency, (tuple, list)) if self.type == VARIABLE: self._latency_distribution = Uniform(*self._latency) elif self.type == NORMAL: self._latency_distribution = Normal(*self._latency) else: # Something went wrong raise UnknownType( "Unkown connection type, {!r}".format(self.type) ) # Non-constant connections (Variable, Normal) value = self._latency_distribution.get() # If value is zero or negative, try again if value <= 1: return self.latency() return value
class Connection(object): """ Create a constant or variable unidirectional connection between a source and a target "connectible" object. If constant, specify latency as an int otherwise specify the latency as a tuple. Connections are necessarily unidirectional so that a single replica can be "taken down" in the simulation, e.g. connections are deactivated to prevent communication; we want to do this without preventing communication in the other direction. """ def __init__(self, network, source, target, **kwargs): self.network = network self.source = source self.target = target self.type = kwargs.get('connection', CONSTANT) self.online = kwargs.get('online', True) self.area = kwargs.get('area', None) # Set the latency protected variable self._latency = kwargs.get( 'latency', settings.simulation.default_latency ) @setter def area(self, value): """ If the area is set directly, then it is stored as such. Otherwise the area is computed by inspecting the locations of the source and the target: if they are the same then local, otherwise wide. """ if value is None: if not self.source or not self.target: return None if self.source.location == self.target.location: return LOCAL_AREA return WIDE_AREA return value def latency(self): """ Computes the latency from the latency range. """ # If we're not online then raise an exception. if not self.online: raise NetworkError( "Cannot get latency for an offline connection!" ) # Constant Connections if self.type == CONSTANT: assert isinstance(self._latency, int) return self._latency if not hasattr(self, '_latency_distribution'): assert isinstance(self._latency, (tuple, list)) if self.type == VARIABLE: self._latency_distribution = Uniform(*self._latency) elif self.type == NORMAL: self._latency_distribution = Normal(*self._latency) else: # Something went wrong raise UnknownType( "Unkown connection type, {!r}".format(self.type) ) # Non-constant connections (Variable, Normal) value = self._latency_distribution.get() # If value is zero or negative, try again if value <= 1: return self.latency() return value def up(self): """ Make the connection online. """ self.online = True def down(self): """ Take the connection offline (cannot send messages) """ self.online = False def get_latency_range(self): """ Returns the latency range no matter the type. """ if self.type == CONSTANT: return (self._latency, self._latency) return self._latency def get_latency_mean(self): """ Returns the mean latency based on the connection type. """ if self.type == CONSTANT: return self.latency else: # Make sure there is a latency distribution _ = self.latency() return self._latency_distribution.get_mean() def get_latency_stddev(self): """ Returns the standard deviation of the latency based on connection type. """ if self.type == CONSTANT: return 0.0 else: # Make sure there is a latency distribution _ = self.latency() return self._latency_distribution.get_stddev() def serialize(self): return { "connection": self.type, "online": self.online, "latency": self._latency, } def __str__(self): """ Returns a representation of the connection object. """ arrow = { CONSTANT: "→", VARIABLE: "⇝", NORMAL: "⇴", }[self.type] return "{} {} {}".format(self.source, arrow, self.target)
class Connection(object): """ Create a constant or variable unidirectional connection between a source and a target "connectible" object. If constant, specify latency as an int otherwise specify the latency as a tuple. Connections are necessarily unidirectional so that a single replica can be "taken down" in the simulation, e.g. connections are deactivated to prevent communication; we want to do this without preventing communication in the other direction. """ def __init__(self, network, source, target, **kwargs): self.network = network self.source = source self.target = target self.type = kwargs.get('connection', CONSTANT) self.online = kwargs.get('online', True) self.area = kwargs.get('area', None) # Set the latency protected variable self._latency = kwargs.get('latency', settings.simulation.default_latency) @setter def area(self, value): """ If the area is set directly, then it is stored as such. Otherwise the area is computed by inspecting the locations of the source and the target: if they are the same then local, otherwise wide. """ if value is None: if not self.source or not self.target: return None if self.source.location == self.target.location: return LOCAL_AREA return WIDE_AREA return value def latency(self): """ Computes the latency from the latency range. """ # If we're not online then raise an exception. if not self.online: raise NetworkError("Cannot get latency for an offline connection!") # Constant Connections if self.type == CONSTANT: assert isinstance(self._latency, int) return self._latency if not hasattr(self, '_latency_distribution'): assert isinstance(self._latency, (tuple, list)) if self.type == VARIABLE: self._latency_distribution = Uniform(*self._latency) elif self.type == NORMAL: self._latency_distribution = Normal(*self._latency) else: # Something went wrong raise UnknownType("Unkown connection type, {!r}".format( self.type)) # Non-constant connections (Variable, Normal) value = self._latency_distribution.get() # If value is zero or negative, try again if value <= 1: return self.latency() return value def up(self): """ Make the connection online. """ self.online = True def down(self): """ Take the connection offline (cannot send messages) """ self.online = False def get_latency_range(self): """ Returns the latency range no matter the type. """ if self.type == CONSTANT: return (self._latency, self._latency) return self._latency def get_latency_mean(self): """ Returns the mean latency based on the connection type. """ if self.type == CONSTANT: return self.latency else: # Make sure there is a latency distribution _ = self.latency() return self._latency_distribution.get_mean() def get_latency_stddev(self): """ Returns the standard deviation of the latency based on connection type. """ if self.type == CONSTANT: return 0.0 else: # Make sure there is a latency distribution _ = self.latency() return self._latency_distribution.get_stddev() def serialize(self): return { "connection": self.type, "online": self.online, "latency": self._latency, } def __str__(self): """ Returns a representation of the connection object. """ arrow = { CONSTANT: "→", VARIABLE: "⇝", NORMAL: "⇴", }[self.type] return "{} {} {}".format(self.source, arrow, self.target)