def access(self): """ Sets up a SimPy event to wait for the access to complete or drop. Note that accesses are only writes - as though this were a sensor just streaming write accesses to the file system! """ # Make sure that there is a device to write to! if not self.device: raise WorkloadException( "No device specified to trigger the access on!") # Make sure that there is a current object to write! if not self.current: raise WorkloadException( "No object specified as currently open on the workload!") # Log the results on the timeseries for the access. self.sim.results.update( WRITE, (self.device.id, self.location, self.current, self.env.now)) # Create the event to wait for the access to complete self._event = self.env.event() self._event.callbacks.append(self.on_event_complete) # Create the access and register the event callbacks if self._access is None: self._access = Write(self.current, self.device) self._access.register_callback(COMPLETED, self.on_access_complete) self._access.register_callback(DROPPED, self.on_access_drop) # Write the access to the local device self.device.write(self._access) # Return the event to register it with the simulation process return self._event
def gossip(self): """ Randomly select a neighbor and exchange information about the state of the latest entries in the log since the last anti-entropy delay. """ # Gossip to one node at each location for location in self.locations: # Don't gossip to nodes in self! if location == self.location: continue # Select a random target to gossip to target = random.choice(list(self.remotes(location))) # Log the gossip that's happening self.sim.logger.debug("{} gossiping {} entries to {}".format( self, len(self.ae_cache), target)) entries = tuple([ Write(version.name, self, version) for version in self.ae_cache ]) # Send all the values in the cache. self.send(target, Gossip(entries, len(self.ae_cache), -1)) # Empty the cache on gossip self.ae_cache = [] # Reset the anti-entropy timer self.ae_timer = Timer(self.env, self.ae_delay, self.gossip) self.ae_timer.start()
def access(self): """ Can reconstruct an access given the information in the version, or the API allows the use of the setter to assign the Write access that created the version for storage and future use. """ if not hasattr(self, '_access'): self._access = Write(self.name, self.writer, version=self, started=self.created, finished=self.updated) return self._access
def write(self, name, **kwargs): """ Exposes the write API for every replica server and is the second of the two primary methods of replica interaction. the write method exepcts the name of the object to write to and creates a Write event with meta informationa bout the write. It is the responsibility of sublcasses to perform the actual write on their local stores with replication. Note that name can also be a Write event and this method is in very different than the old write method (see details in read). This method will be adapted in the future to deal with write sizes, blocks, and other write meta information. """ if not name: raise AccessError( "Must supply a name to write to the replica server") return Write.create(name, self, **kwargs)
def write(self, name, **kwargs): """ Exposes the write API for every replica server and is the second of the two primary methods of replica interaction. the write method exepcts the name of the object to write to and creates a Write event with meta informationa bout the write. It is the responsibility of sublcasses to perform the actual write on their local stores with replication. Note that name can also be a Write event and this method is in very different than the old write method (see details in read). This method will be adapted in the future to deal with write sizes, blocks, and other write meta information. """ if not name: raise AccessError( "Must supply a name to write to the replica server" ) return Write.create(name, self, **kwargs)
def access(self): """ Sets up a SimPy event to wait for the access to complete or drop. Note that accesses are only writes - as though this were a sensor just streaming write accesses to the file system! """ # Make sure that there is a device to write to! if not self.device: raise WorkloadException( "No device specified to trigger the access on!" ) # Make sure that there is a current object to write! if not self.current: raise WorkloadException( "No object specified as currently open on the workload!" ) # Log the results on the timeseries for the access. self.sim.results.update( WRITE, (self.device.id, self.location, self.current, self.env.now) ) # Create the event to wait for the access to complete self._event = self.env.event() self._event.callbacks.append(self.on_event_complete) # Create the access and register the event callbacks if self._access is None: self._access = Write(self.current, self.device) self._access.register_callback(COMPLETED, self.on_access_complete) self._access.register_callback(DROPPED, self.on_access_drop) # Write the access to the local device self.device.write(self._access) # Return the event to register it with the simulation process return self._event
class StreamingWorkload(Workload): """ A streaming workload issues accesses one after the other as soon as the previous access is dropped or completed (with some minimal delay between accesses that can be specified by overriding the `wait` method). """ def __init__(self, sim, **kwargs): # Get the delay in milliseconds if specified self.delay = kwargs.pop("delay", 10) # Internal parameters self._event = None self._access = None # Initialize the workload super(StreamingWorkload, self).__init__(sim, **kwargs) def on_access_drop(self, access): # Retry the access after a delay self._access = access.clone(self.device) self._event.succeed() def on_access_complete(self, access): # Set the access to None to generate a new write self._access = None self._event.succeed() def on_event_complete(self, event): # Wait for a bit and execute the next access! self.env.process(self.wait()) def wait(self): """ Wait a fixed delay and then cause the access to occur! """ yield self.env.timeout(self.delay) yield self.access() def access(self): """ Sets up a SimPy event to wait for the access to complete or drop. Note that accesses are only writes - as though this were a sensor just streaming write accesses to the file system! """ # Make sure that there is a device to write to! if not self.device: raise WorkloadException( "No device specified to trigger the access on!") # Make sure that there is a current object to write! if not self.current: raise WorkloadException( "No object specified as currently open on the workload!") # Log the results on the timeseries for the access. self.sim.results.update( WRITE, (self.device.id, self.location, self.current, self.env.now)) # Create the event to wait for the access to complete self._event = self.env.event() self._event.callbacks.append(self.on_event_complete) # Create the access and register the event callbacks if self._access is None: self._access = Write(self.current, self.device) self._access.register_callback(COMPLETED, self.on_access_complete) self._access.register_callback(DROPPED, self.on_access_drop) # Write the access to the local device self.device.write(self._access) # Return the event to register it with the simulation process return self._event def run(self): """ Sets off the first event that starts streaming access events. """ return self.wait()
class StreamingWorkload(Workload): """ A streaming workload issues accesses one after the other as soon as the previous access is dropped or completed (with some minimal delay between accesses that can be specified by overriding the `wait` method). """ def __init__(self, sim, **kwargs): # Get the delay in milliseconds if specified self.delay = kwargs.pop("delay", 10) # Internal parameters self._event = None self._access = None # Initialize the workload super(StreamingWorkload, self).__init__(sim, **kwargs) def on_access_drop(self, access): # Retry the access after a delay self._access = access.clone(self.device) self._event.succeed() def on_access_complete(self, access): # Set the access to None to generate a new write self._access = None self._event.succeed() def on_event_complete(self, event): # Wait for a bit and execute the next access! self.env.process(self.wait()) def wait(self): """ Wait a fixed delay and then cause the access to occur! """ yield self.env.timeout(self.delay) yield self.access() def access(self): """ Sets up a SimPy event to wait for the access to complete or drop. Note that accesses are only writes - as though this were a sensor just streaming write accesses to the file system! """ # Make sure that there is a device to write to! if not self.device: raise WorkloadException( "No device specified to trigger the access on!" ) # Make sure that there is a current object to write! if not self.current: raise WorkloadException( "No object specified as currently open on the workload!" ) # Log the results on the timeseries for the access. self.sim.results.update( WRITE, (self.device.id, self.location, self.current, self.env.now) ) # Create the event to wait for the access to complete self._event = self.env.event() self._event.callbacks.append(self.on_event_complete) # Create the access and register the event callbacks if self._access is None: self._access = Write(self.current, self.device) self._access.register_callback(COMPLETED, self.on_access_complete) self._access.register_callback(DROPPED, self.on_access_drop) # Write the access to the local device self.device.write(self._access) # Return the event to register it with the simulation process return self._event def run(self): """ Sets off the first event that starts streaming access events. """ return self.wait()