예제 #1
0
    def read_via_policy(self, name):
        """
        This method returns a version from either the log or the cache
        according to the read policy set on the replica server as follows:

            - COMMIT: return the latest commited version (ignoring cache)
            - LATEST: return latest version in log or in cache

        This method raises an exception on bad read policies.
        """

        # If the policy is read committed, return the latest committed version
        if self.read_policy == ReadPolicy.COMMIT:
            return self.log.get_latest_commit(name)

        # If the policy is latest, read the latest and compare to cache.
        if self.read_policy == ReadPolicy.LATEST:
            # Get the latest version from the log (committed or not)
            version = self.log.get_latest_version(name)

            # If name in the cache and the cache version is greater, return it.
            if name in self.cache and version is not None:
                if self.cache[name] > version:
                    return self.cache[name]

            # Return the latest version
            return version

        # If we've reached this point, we don't know what to do!
        raise SimulationException("Unknown read policy!")
예제 #2
0
파일: vcs.py 프로젝트: bbengfort/cloudscope
    def update(self, replica, commit=False, forte=False, **kwargs):
        """
        The update method allows a Raft leader to now also update the forte
        on this particular instance version. The method does a quick sanity
        check just to make sure only the leader can do this, then happily
        performs the forte update.
        """
        if forte:
            if not replica.consistency in {
                    Consistency.STRONG, Consistency.RAFT
            }:
                raise SimulationException(
                    "{} attempting to set forte with consistency {}".format(
                        replica, replica.consistency))

            if not replica.state == State.LEADER:
                raise SimulationException(
                    "{} attempting to set forte in state {}".format(
                        replica, replica.state))

            self.forte = self.increment_forte()

        super(FederatedVersion, self).update(replica, commit, **kwargs)
예제 #3
0
    def on_state_change(self):
        """
        Setting the state decides how the Tag node will interact.
        """

        # Do state specific tag modifications
        if self.state == State.READY:
            self.votes = None
            self.tag = None

            # Remove owner state
            self.nextIndex = None
            self.matchIndex = None

            # Also interrupt the heartbeat
            if self.heartbeat: self.heartbeat.stop()

        elif self.state == State.TAGGING:
            # Convert to tag acquisition/release
            self.epoch += 1

            # Create election and vote for self
            self.votes = Election([node.id for node in self.quorum()])
            self.votes.vote(self.id)

            # Also interrupt the heartbeat
            if self.heartbeat: self.heartbeat.stop()

        elif self.state == State.OWNER:

            # Create the next index and match index
            self.nextIndex = {
                node: {
                    obj: self.log[obj].lastApplied + 1
                    for obj in self.view[self]
                }
                for node in self.neighbors()
            }

            self.matchIndex = {
                node: {obj: 0
                       for obj in self.view[self]}
                for node in self.neighbors()
            }

        else:
            raise SimulationException(
                "Unknown Tag Replica State: {!r} set on {}".format(
                    state, self))
예제 #4
0
    def get_leader_node(self):
        """
        Searches for the leader amongst the neighbors. Raises an exception if
        there are multiple leaders, which is an extreme edge case.
        """
        leaders = [
            node for node in self.quorum() if node.state == State.LEADER
        ]

        if len(leaders) > 1:
            raise SimulationException("MutipleLeaders?!")
        elif len(leaders) < 1:
            return None
        else:
            return leaders[0]
예제 #5
0
    def run(self):
        """
        Implements the Raft consensus protocol and elections.
        """
        while True:
            if self.state in {State.FOLLOWER, State.CANDIDATE}:
                yield self.timeout.start()

            elif self.state == State.LEADER:
                yield self.heartbeat.start()

            else:
                raise SimulationException(
                    "Unknown Raft State: {!r} on {}".format(self.state, self)
                )
예제 #6
0
    def on_state_change(self):
        """
        Does the same stuff as super, but also - if leader; starts the anti
        entropy interval to do gossiping.
        """
        super(FloatedRaftReplica, self).on_state_change()

        if self.state in (State.FOLLOWER, State.CANDIDATE):
            if hasattr(self, 'ae_timer') and self.ae_timer is not None:
                # Cancel the anti-entropy timer.
                self.ae_timer.stop()
                self.ae_timer = None
        elif self.state == State.LEADER:
            self.ae_timer = Timer(self.env, self.ae_delay, self.gossip)
            self.ae_timer.start()
        elif self.state == State.READY:
            # This happens on the call to super, just ignore for now.
            pass
        else:
            raise SimulationException(
                "Unknown Floating Raft State: {!r} set on {}".format(
                    self.state, self))
예제 #7
0
 def on_state_change(self):
     """
     When the state on a replica changes the internal state of the replica
     must also change, particularly the properties that define how the node
     interacts with RPC messages and client reads/writes.
     """
     if self.state in (State.FOLLOWER, State.CANDIDATE):
         self.votedFor    = None
         self.nextIndex   = None
         self.matchIndex  = None
     elif self.state == State.CANDIDATE:
         pass
     elif self.state == State.LEADER:
         self.nextIndex   = {node: self.log.lastApplied + 1 for node in self.quorum() if node != self}
         self.matchIndex  = {node: 0 for node in self.quorum() if node != self}
     elif self.state == State.READY:
         # This happens on the call to super, just ignore for now.
         pass
     else:
         raise SimulationException(
             "Unknown Raft State: {!r} set on {}".format(self.state, self)
         )
예제 #8
0
 def select_anti_entropy_neighbor(self):
     """
     This is a No-Op for this type of replica.
     """
     raise SimulationException(
         "Stentor replicas do not have a single neighbor selection policy.")
예제 #9
0
 def run(self):
     raise SimulationException(
         "Timers cannot be run, they should be started and stopped!")