def write_via_policy(self, name): """ This method returns a new version incremented from either from the log or from the cache according to the read policy. It also handles any "new" writes, e.g. to objects that haven't been written yet. """ # Fetch the version from the log or the cache according to the # read policy. This implements READ COMMITTED/READ LATEST latest = self.read_via_policy(name) # Perform the write if latest is None: return namespace(name)(self) return latest.nextv(self)
def write(self, name, **kwargs): """ When a replica performs a write it needs to decide if it can write to the tag locally, can acquire a tag for this object, or if it has to do something else like drop, wait, or remote write. If the access is local: - if the replica owns the tag, append and complete - if someone else owns the tag then drop, wait, or remote - if no one owns the tag, then attempt to acquire it If access is remote: - if we own the tag, then append but do not complete (at local) - if someone else owns the tag, log and forward to owner - if no one owns the tag then respond false """ # Create the read event using super. access = super(TagReplica, self).write(name, **kwargs) # Increase the session on access. self.handle_session() # Determine if the write is local or remote if access.is_local_to(self): # Record the number of attempts for the access access.attempts += 1 # Fetch the latest version from the log. latest = self.log[access.name].lastVersion # Perform the write if latest is None: version = namespace(access.name)(self) else: version = latest.nextv(self) # Update the access with the latest version access.update(version) else: # If there is no version, raise an exception if access.version is None: raise AccessError( "Attempting a remote write on {} without a version!".format(self) ) # Save the version variable for use below. version = access.version # Log the access at this replica access.log(self) # Are we the owner of this tag? if self.owns(access.name): # Perform the append entries self.log[name].append(version, self.epoch) # Update the version to track visibility latency version.update(self) # Complete the access if it was local if access.is_local_to(self): access.complete() # Now do AppendEntries # Also interrupt the heartbeat since we just sent AppendEntries if not settings.simulation.aggregate_writes: self.send_append_entries() if self.heartbeat: self.heartbeat.stop() return access # Is there a different owner for the tag? owner = self.find_owner(name) if owner is not None: # Right now just drop the write on its face. self.sim.logger.info( "ownership conflict: dropped {} at {}".format(access, self) ) return access.drop() # We're going to acquire the tag! else: # We're going to have some write latency, retry the write. retry = Timer( self.env, self.heartbeat_interval, lambda: self.write(access) ).start() # Request the ownership of the tag self.acquire(access.name) return access
def write(self, name, **kwargs): """ When a replica performs a write it needs to decide if it can write to the tag locally, can acquire a tag for this object, or if it has to do something else like drop, wait, or remote write. If the access is local: - if the replica owns the tag, append and complete - if someone else owns the tag then drop, wait, or remote - if no one owns the tag, then attempt to acquire it If access is remote: - if we own the tag, then append but do not complete (at local) - if someone else owns the tag, log and forward to owner - if no one owns the tag then respond false """ # Create the read event using super. access = super(TagReplica, self).write(name, **kwargs) # Increase the session on access. self.handle_session() # Determine if the write is local or remote if access.is_local_to(self): # Record the number of attempts for the access access.attempts += 1 # Fetch the latest version from the log. latest = self.log[access.name].lastVersion # Perform the write if latest is None: version = namespace(access.name)(self) else: version = latest.nextv(self) # Update the access with the latest version access.update(version) else: # If there is no version, raise an exception if access.version is None: raise AccessError( "Attempting a remote write on {} without a version!". format(self)) # Save the version variable for use below. version = access.version # Log the access at this replica access.log(self) # Are we the owner of this tag? if self.owns(access.name): # Perform the append entries self.log[name].append(version, self.epoch) # Update the version to track visibility latency version.update(self) # Complete the access if it was local if access.is_local_to(self): access.complete() # Now do AppendEntries # Also interrupt the heartbeat since we just sent AppendEntries if not settings.simulation.aggregate_writes: self.send_append_entries() if self.heartbeat: self.heartbeat.stop() return access # Is there a different owner for the tag? owner = self.find_owner(name) if owner is not None: # Right now just drop the write on its face. self.sim.logger.info("ownership conflict: dropped {} at {}".format( access, self)) return access.drop() # We're going to acquire the tag! else: # We're going to have some write latency, retry the write. retry = Timer(self.env, self.heartbeat_interval, lambda: self.write(access)).start() # Request the ownership of the tag self.acquire(access.name) return access